Troubleshooting
My app doesn’t show up in the dev console
Section titled “My app doesn’t show up in the dev console”- Check
linkworld loginsucceeded —~/.config/linkworld/config.jsonshould have atokenfield. - Hit
https://linkworld.ai/api/dev/mewith the token — should return your dev account. - If you used
linkworld init, you also needlinkworld deployat least once before the app appears under “Your apps”.
linkworld deploy says “manifest validation failed”
Section titled “linkworld deploy says “manifest validation failed””The CLI runs the same Pydantic schema as the platform. Read the error carefully — it points at the field. Common causes:
- Tool name not lowercase:
BadNameshould bebad_name - Top-level field misspelled:
runtimeImage:instead ofruntime: { image: ... } apiVersionnot exactlylinkworld.ai/v2runtime.portoutside 1024–65535
ctx.tools.call(...) raises ToolCallError(scope_denied)
Section titled “ctx.tools.call(...) raises ToolCallError(scope_denied)”The tenant didn’t grant the scope your tool call needs. Fixes:
- Confirm the scope is in your
manifest.required_scopes. - The tenant admin must re-install (or re-grant) on their side.
- Catch and degrade gracefully — see Best practices.
ctx.secrets.get(...) returns null
Section titled “ctx.secrets.get(...) returns null”Walk the lookup chain:
- Did you
linkworld secrets set KEY=...for the dev-default? Checklinkworld secrets list --app <slug>. - The key must match
^[A-Z][A-Z0-9_]{0,63}$. Lowercase or spaces fail silently — the SDK validates client-side. - Network error reaching the platform also returns
null(fail-closed). Check container logs for the underlying error.
My handler isn’t firing
Section titled “My handler isn’t firing”For lifecycle hooks: check manifest.lifecycle.<hook>: true. The SDK
refuses to register a handler whose flag is false at construction time
— if app.run() started without complaint, the wiring is correct.
For on_inbound: the tenant has to opt into fan-out for your app
in their app-settings UI. Without that opt-in, the platform routes the
inbound to its standard agent and your app never sees it.
For schedules: the platform’s leader-elected scanner ticks every 60s.
If your cron is * * * * *, expect ±60s jitter. If you see no ticks
at all, check your cron syntax — 0 8 * * 1-5 runs Mon-Fri at 08:00,
not every 8 hours.
Container won’t start
Section titled “Container won’t start”Check the container logs in the dev console (Logs tab) or in your
local docker logs if running via linkworld deploy --skip-build on
a self-hosted VM:
platform credentials missing: the platform didn’t injectLINKWORLD_MCP_URL/LINKWORLD_MCP_TOKEN. Probably a platform-side bug — file an issue.- Health check fails: your
runtime.portdoesn’t match the port your handler binds to. Fix the manifest. - Image pull fails: the GHCR image isn’t public. Either make it public or coordinate with the platform admin to add pull credentials.
”OAuth completed but token was rejected”
Section titled “”OAuth completed but token was rejected””The OAuth flow worked but the JWT validation in /api/dev/me failed.
Most likely:
- The dev-account row was suspended after the JWT was minted.
- Wall-clock skew between the platform and the JWT issuer (rare; both are NTP-synced).
- The platform’s
supabase_jwt_secretrotated (very rare; coordinate with admin).
Sign out, sign in again. If the new token also fails, contact platform support.
Local mode acts weird
Section titled “Local mode acts weird”LINKWORLD_LOCAL=1is required (orapp.run({ local: true })). Without it the SDK tries to find platform credentials and refuses to start.- The mock tools have to be registered before they’re called. If a
handler calls
email_sendand you haven’tPOST /__mock/toolfor it yet, you getToolCallError(decision='not_found'). - The
/__mock/secretendpoint sets in-process state; restart the app and you start fresh.
My audit log is empty
Section titled “My audit log is empty”- Audit rows are written per tool call. If your handler doesn’t call any platform tools, it doesn’t produce audit rows.
- The Logs tab polls every 10s. Newly-arrived rows take up to that long to appear.
- In local mode, audit rows go to stdout, not the platform — they don’t show up in any dev console.
Deploy script keeps timing out
Section titled “Deploy script keeps timing out”The platform’s image registration call to GHCR can be slow on first publish (it pulls the image to verify it’s reachable). Default timeout is 60s. Workarounds:
# Pre-pull the image yourself firstdocker pull ghcr.io/you/my-app:0.1.0linkworld deploy --skip-build --version 0.1.0If it still times out, check that the image is public on GHCR or that the platform’s pull token has access.