Skip to main content

Troubleshooting

Every message below is quoted from the code or from a measured run.

Startup and environment​

AILANG_REGISTRY_API_KEY is set in the process environment​

ailang-worldd: broker: AILANG_REGISTRY_API_KEY is set in the process environment: move it to a mode-0600 file outside the working tree and unset it (see design_docs/planned/w-self-mod-vertical.md Decision 4)

Every ailang-worldd command refuses (exit 2), client verbs included. Run unset AILANG_REGISTRY_API_KEY in that shell. world-publish reads the key only from --credential-file.

another process already holds writer authority for this database​

Another process has the store open for writing: usually your running daemon. session mint, session revoke and world-publish transitions all need the daemon stopped first. The lock file is <db>.writer.lock; do not delete it by hand while a process holds it.

resolve parent of "…": no such file or directory / STOP fence=store reason=unopenable​

The store refuses to create its parent directory. mkdir -p it first.

STOP fence=store reason=unopenable … has user_version 2 … binary requires 4; refusing to modify​

The store was written by an older binary and there is no migration. Use a fresh store file and leave the old one untouched.

bind host "…" is not loopback​

serve accepts only 127.0.0.1, ::1 or localhost in --bind. There is no override.

--addr is a client flag and is not valid for 'serve'​

Use --bind with serve. --addr (with a scheme, for example http://127.0.0.1:7645) goes before a client verb: ailang-worldd --addr http://127.0.0.1:7645 health.

tool binary is "…"; only "AILANG v0.52.1" is measured for the workspace tools​

--tool-ailang-bin must be exactly AILANG v0.52.1. See Install.

the workspace root is refused / … is inside --workspace-root​

The store, its archive, policies/ or cache/ directory, or the examples corpus lies inside --workspace-root. An agent that can edit its own policy has no policy. Put the store in a directory outside the workspace root.

Attended steps​

STOP fence=tty reason=stdin-is-not-the-controlling-terminal​

world-publish was run with stdin that is a character device but not /dev/tty, typically an IDE pane or an agent harness. Append < /dev/tty and type the phrase yourself.

STOP fence=tty reason=no-controlling-terminal​

There is no terminal at all. A headless process cannot do this step; a human must.

refusing: no controlling terminal (…); minting a session credential requires one human act at a terminal​

Same, for session mint. Run it at a real terminal.

STOP fence=confirmation reason=mismatch​

The typed line is not the exact phrase. approve and publish ask for publish world/core@0.1.1 irreversibly; transitions asks for publish <N> transitions to <store>, with the manifest's descriptor count and the --store you gave. Type the line exactly as printed. See Attended steps.

interpreter release "…" is nominated by NO epoch in world/epoch-registry/v1​

world-publish transitions was pointed at a store whose daemon has never run with this interpreter. Start serve --ailang-bin $PIN once against the store, stop it, then publish.

… is not loadable under its pinned interpreter / LDR001​

The transition source failed check under the pinned interpreter. A common cause is importing world/*: publishable modules must be self-contained and import only std/*.

session revoke: usage: session revoke [--db <path>] <credential_id-hash> (flags before the id)​

Flags after the ID are not parsed. Put --db before the credential ID: session revoke --db /path/world.db <credential_id>.

Committing​

401 SessionAbsent on commit​

ailang-worldd: /v1/commit returned HTTP 401 SessionAbsent: a session credential is required: no Authorization Bearer header was present

POST /v1/commit is session-gated. Pass --session "$(cat /path/session)" to commit, or send Authorization: Bearer <token>. This also means the genesis commit comes after session mint. Older runbook text that commits genesis without a session no longer works.

The related classes: 400 InvalidSession (malformed header), 401 SessionUnknown (revoked or never minted, or minted in a different store), 401 SessionExpired.

409 HeadConflict​

The world moved since the head you observed. The body carries observedHead and selectedHead; re-plan against the selected head.

503 CommitUncertain​

The commit budget ended after the durable step began. It landed whole or not at all. Do not resend until you have read the log row at your entry's index (or the receipt, if you sent an invocationId). The current head is not evidence either way.

500 internal store failure on a commit you built yourself​

A payload whose bytes do not hash to its stated hash is refused by the store, but the route currently reports it as an internal failure rather than a client error (finding F-3 of the value demonstration). Check every object hash is sha256: of the exact payload bytes. The daemon's stderr has the real cause.

MCP and the coding tools​

The /mcp/ response is event: message / data: …​

That is correct. /mcp/ answers with SSE framing; the JSON-RPC object is on the data: line. Send both Content-Type: application/json and Accept: application/json, text/event-stream, or the request is refused with Accept must list both application/json and text/event-stream.

tools/list is empty, or a tool is missing​

A session sees only tools whose access effect it holds a live grant for. Check the grants you minted, that the session has not expired, and that the transitions are published in this store (ailang-worldd registry get world/transition-registry/v1).

workspace tools disabled​

ailang-worldd: workspace tools disabled: --workspace-root and --tool-ailang-bin must both be set; every effect-declaring transition is refused

Start serve with both flags. Until then every tool call is refused before any effect runs (rule R8). Over A2A the refusal reads transition declares an effect this daemon has no handler for; over MCP the whole request answers host callback failed.

workspace tools unavailable for episode "…"​

The episode's handler could not be built: check that <workspace-root>/<episode> exists, is a real directory and not a symlink, that the episode ID matches ^[a-z0-9][a-z0-9-]{0,63}$, and that the tool binary still verifies. The episode then gets an empty handler registry.

{"ok":false,"refused":"no examples corpus configured: …"}​

examples-search has no corpus. Run $TOOL examples download (fills ~/.ailang/examples) or start serve with --examples-dir DIR, outside the workspace root.

{"ok":false,"refused":"…"} with effects: []​

The tool's own plan refused the arguments: an unknown key, a missing required key, or a path that is absolute, empty, contains .. or starts with -. The refusal is committed.

denied:budget​

The episode has spent its grant. Budget persists per episode across restarts and across new sessions for the same episode; use a new episode (and worktree) for a fresh budget.

transition invocation is not available in this daemon​

serve ran without --ailang-bin, so there is no invocation coordinator, or a registry read failed. Check the daemon's stderr for an a2a refusal line with the cause.

effects were requested but the invocation was not confirmed committed; effect records: …​

Over A2A: the effect ran and was recorded, but the commit did not land (for example another writer moved the head). The listed effect records are durable. Do not assume the effect did not happen. See MCP and A2A.

pi or claude hangs when run from a script​

Both read a non-TTY stdin as extra prompt input and wait for EOF. Give them </dev/null.

pi shows the World tools only through a proxy​

pi-mcp-adapter registers direct tools from its cache (~/.pi/agent/mcp-cache.json). Run one interactive pi --mcp-config … session first to write it.