w6w docs

Troubleshooting

Find your symptom below. Startup refusals are deliberate: the server stops with a message naming the setting rather than running in a state you did not intend.

SymptomCauseWhat to do
/commerce or /commerce/… answers 404 commerce_unavailableNot a failure. A self-host install has no commerce surface: every /commerce request gets this built-in stub, unauthenticated, and nothing is forwarded anywhere.Nothing — this is the intended answer.
GET /health/ready answers 401Readiness is bearer-guarded.Probe with an operator token, or use the unauthenticated GET /health instead.
Activate answers 409 link_not_configuredThe warden has no vendor address to activate against.Configure it, or use the offline path (see Air-gapped installs).
Activate answers 409 identity_unavailableThis installation’s private key can’t be decrypted.Usually W6W_CREDENTIAL_KEY was changed or lost after first boot — the stored key is unrecoverable, so the installation must be re-provisioned.
Activate answers 424 control_unavailableThe control plane was unreachable, answered a server error, or returned a malformed success body.Check W6W_CONTROL_URL, your egress, and try again — nothing is retried for you.
Activate answers 400 activation_rejectedYour vendor refused the token (unknown, expired, or already used).Ask for a fresh activation token.
Activate answers 409 already_activatedThis host already has an installation id.Re-activation isn’t supported host-side — ask your vendor to work from the installation record.
GET /installation stays at base level even though you installed a licenceThe warden is absent, not activated, unreachable or revoked, or the licence is past its end.Run w6w-warden status, activate or renew at the warden, and read its log.
Migrations fail with relation "connections" does not existThe migration runner was pointed at an empty database.Bootstrap with the install step first (see Install); run the migration runner only against an already-installed database.
Startup refuses with: “Refusing to start: this image (version <image version>) does not recognize applied migration(s) <ids> recorded in schema_migrations. This image’s newest known migration is <newest>. The database was migrated by a newer or incompatible image — upgrade this image to match it, or restore the database from a compatible backup.”The database was already migrated by a newer image than the one now booting.Upgrade this image to match, or restore the database from a backup taken at a compatible version — see Upgrade.
Startup refuses with: “Refusing to start: role “<role>” is missing <USAGE, CREATE> on schema “<schema>”. Run this as a superuser, then retry: GRANT <privileges> ON SCHEMA <schema> TO "<role>";”The connecting Postgres role lacks schema privileges — checked before any migration runs, so this fails fast instead of mid-migration.Run the printed GRANT ... ON SCHEMA ... TO "<role>"; statement as a superuser, then retry.
Startup refuses with: “Refusing to start: W6W_IMPORT_PACK must be unset or “official”, got <value>.”W6W_IMPORT_PACK was set to something other than exactly official.Unset it, or set it to exactly official.
POST /apps/import-pack answers 404 with {"error":{"code":"official_pack_unavailable","message":"No official app pack found: w6w-pack.json is absent from both <dir> and <parent dir>."}}This image has no baked-in official app pack to import.Nothing to import — register apps individually instead, or use an image that bakes one in.
POST /apps/import-pack otherwise answers 201 (newly registered) or 200 (already present), or 207 if some entries in the pack failedNot a failure by itself — the status names how the import went.On 207, check the response body’s per-entry results for which ones failed and why.
The boot-time W6W_IMPORT_PACK=official import logs exactly one summary line either way: [official-pack] <registered> registered, <already present> already present, <failed> failed of <total> (<ms> ms)Informational — the whole record of what an automatic import did.Check this line if apps you expected aren’t registered; a nonzero failed count also lists which entries and why.
An imported app has no icon or screenshot, and the server log shows asset-inliner: dropped …The local icon/screenshot ref is not a regular image file (svg, png, jpg, jpeg, webp, gif, ico) of at most 1 MiB inside the app’s own directory (absolute path, .., a symlink out, a hardlinked file, oversize). The import still succeeds; fix the ref or file and re-import.
An import answers 400 naming bad_ref, unsafe_cache_path, or a pack entry unsafe "path"The source ref (owner/repo or @ref segments) or a w6w-pack.json entry path is outside the allowed form (for example contains ..). Correct the ref or the pack file.
Startup refuses, naming W6W_INSTALLATION_MODEThe value names the other profile than the one this image was built for.Unset it, or set it to match the image.
Startup refuses, naming W6W_EDGESA self-host install always serves exactly the same three surfaces.Unset W6W_EDGES.
Startup refuses, naming W6W_CONTROL_URLThe value isn’t a valid http:///https:// URL.Fix it, or unset it.
Startup refuses, naming AUTH_PASSWORDBoot safety: the default credential isn’t allowed outside development.Set a real AUTH_PASSWORD.
Startup refuses, naming OPS_JWT_SECRET/JWT_SECRETThe two signing secrets collide.Give OPS_JWT_SECRET a value distinct from JWT_SECRET, or leave it unset (which also disables publishing built apps through /system-ops/apps/artifacts).
Invocations answer 429 concurrency_exceeded; runs sit queuedThe install is at its licensed parallel-execution cap.Wait for the Retry-After the response names, or license more parallel executions.
New work answers 402 licence_lapsedThe licence has lapsed.Renew it. Work already running finishes, and you can still sign in.
Commerce relay is unavailableThe configured warden cannot be reached or has no commerce service.Check w6w-warden status and the warden service.
Warden status says unreachableThe socket or remote TLS endpoint cannot be reached.Check W6W_WARDEN, W6W_WARDEN_URL, socket permissions and the warden service; the host stays at base level.
The installation stays at base levelThe warden is absent, not activated, unreachable, revoked, or past its licence period.Run w6w-warden status, activate or renew at the warden, and check its logs.
A spoke fails a step with spoke_app_mismatchThe spoke and hub run different versions, or the run is pinned to an older app version.Run one image version everywhere (see Hub and spokes).
A spoke refuses to startDATABASE_URL or a credential key is set in its environment, or its key file is readable by group or others.Unset those variables; chmod 600 the file named by W6W_SPOKE_KEY_FILE.
GET /metrics answers 403 or 404404: W6W_METRICS_ENABLED is off. 403: the caller is not in W6W_METRICS_ALLOW_CIDRS, or the request came through a proxy.See Metrics.