Troubleshooting

Orchestration problems on hosted nfltr.xyz, by symptom: what you see, why, and the fix. Most failures reach the hub as an agent completion it can act on; the rest show when a command starts.

Start with the readiness check; it names the relay the CLI resolved, whether the relay accepts your key, whether claude is installed and logged in, and how many nodes and workers it sees. It counts only nodes that serve this project's hub: a node joined with --serve-hubs naming other hubs is listed apart, and if it is the only one the check fails.

$ nfltr orch doctor

"API key rejected by relay (HTTP 403)"

Symptom: nfltr orch "<goal>" stops with the hub cannot start: API key rejected by relay (HTTP 403): invalid API key — save a valid key with `nfltr config add-api-key`, or set NFLTR_API_KEY and exits 1 before any model runs; nfltr orch doctor fails its relay row the same way. In Claude Code the nfltr server stays connected and its server_status tool returns the same reason, so the session can tell you. Fix: create or copy a key in the dashboard and save it with nfltr config add-api-key, or set NFLTR_API_KEY; never put it on a command line.

With no key at all, nfltr orch nodes list says no API key for relay …: save your nfltr.xyz key with `nfltr config add-api-key`, or set NFLTR_API_KEY.

A node is missing

Symptom: nfltr orch nodes list does not show a machine, or the hub says no node matches.

$ nfltr orch nodes list

tools_not_allowed

Symptom: an agent completes with tools_not_allowed, naming the node and the denied calls.

Why: the node joined without --allow-all-tools, so its agents may edit files but every command that needs approval (shell, git push, reading outside the task checkout) is refused. Fix: stop the node and join it again with --allow-all-tools. For the zero-setup local hub: nfltr orch nodes stop, then rerun nfltr orch --allow-all-tools (in Claude Code, re-add the server as claude mcp add nfltr -- nfltr orch hub --max-agents 2 --allow-all-tools). There it applies only to the local node the command starts; a node on another machine keeps the flags it joined with.

"no connected worker satisfies constraints …"

Why: nothing eligible for the spawn's machine, labels or repository connected within its bound (the spawn's timeout_ms, else about 30 seconds). The error lists what was connected. Fix: check the machine id and labels in nfltr orch nodes list, start or rejoin the node, and ask the hub to retry. With several harnesses installed on a node, join it with --harness claude-code (or have the spawn name one).

"timeout_ms … elapsed with no connected worker …"

Why: the spawn's own timeout_ms passed while nothing eligible was connected. When it adds N agent process(es) a node launched for it never connected, a node accepted the launch and then stopped or lost its connection before the agent registered. (… before an eligible worker had a free slot means the machines were connected but full.) Fix: as above: check nfltr orch nodes list and rejoin the node.

A repository is refused

Why: the spawn named a repository that matches none of the node's --allow-repo globs, so no node takes it. While the agent waits, its waiting says so for each node, for example none admits it: node on my-laptop advertises nfltr.workspace_repo_allow="", which does not admit repository "https://github.com/your-org/app" (its --allow-repo patterns match none). When its timeout_ms passes it ends with … constraints {workspace.repo=…}; last launch: no connected node admits repository "…": it matches none of their nfltr.workspace_repo_allow patterns (my-laptop@my-laptop allows none (joined without --allow-repo)). Fix: rejoin the node with a matching glob and --allow-all-tools (repository work needs a shell), for example --allow-all-tools --allow-repo 'github.com/your-org/*'. The node must also be able to fetch it for its mirror, with the machine's own git credentials.

node_lost

Why: the node was killed, stopped (Ctrl-C, SIGTERM), or its machine went away, while the agent ran. The node owns its agents, so they end with it. A node that stops (Ctrl-C, SIGTERM) reports its agents at once; one that lost its connection is reported about 30 seconds after it left, unless it comes back sooner. What happens: the hub receives node_lost as a completion and decides; it can re-issue the work. A spawn that names the machine waits for it to rejoin (up to its timeout_ms) and then runs there. Fix: run the same nfltr node join again on that machine.

budget_exceeded

Why: the hub's --hub-max-tokens/--hub-max-usd, or an agent's own budget, was reached. Running turns are stopped and further spawns and messages refused. Token caps count input, output and cache-write tokens; the message shows cache-read tokens apart (not counted) names the caps and what they cover (the hub budget (max_tokens=6000, max_usd=$2 for all agents of this hub together) was passed: they used …) and says cost not reported for tokens of turns that reported no cost (claude reports a turn's cost only when it ends, so a stopped or lost turn never does; nfltr does not estimate it). Fix: start the hub with a higher cap. The stopped turns' uncommitted edits come back as recovery patches, so work is not lost.

Relay restart or deploy window

Symptom: a short connection outage. Nodes and agents reconnect by themselves; a hub started during the window waits up to two minutes for the relay before failing with the relay address. A spawn that could not dispatch stays pending, within its bound, and runs when the nodes are back. A dropped task stream is resumed, not reported as a failure. Fix: usually nothing; if a hub start failed, run it again.

An agent is slow to notice a lost connection

Why: when the relay vanishes without closing the connection (power loss, a NAT or Wi-Fi change), the agent learns of it only because the relay's heartbeats stop arriving. Fix: pick a keepalive preset with --keepalive (or NFLTR_KEEPALIVE, or keepalive: in an nfltr up file). For example, nfltr http 3000 --keepalive fast, or nfltr node join --max-agents 2 --keepalive mobile.

PresetUse it forNotices withinIdle traffic per agent
fastquick failover, interactive use~5 s~36 B/s
defaultbalanced15 s~11 B/s
natlong idle behind NATs and load balancers30 s~5 B/s
datacenterstable networks45 s~4 B/s
mobilelaptops and phones on flaky Wi-Fi or metered links60 s~4 B/s

nfltr diagnose shows the effective setting.

The hub exited

Agents keep running without their hub. After Ctrl-C the session names them: interrupted; 1 agent(s) of hub … keep running (… on node-…) and their results are kept: run `nfltr orch --hub-id … "<goal>"` … to collect them. Run nfltr orch again in the same project directory (the default hub id is per project), or pass the same --hub-id; the hub reattaches and receives every completion it missed, exactly once.

$ nfltr orch --hub-id release-check

A hub session does the work itself, or asks you to approve commands

Why: a Claude Code session with its own shell and file tools can work locally instead of spawning; under claude -p its commands then need approval it cannot get. nfltr orch "<goal>" starts its session with only the hub tools, so its work runs in agents. Fix: in your own session, say where the work should run ("have an agent on the build server do this"); with nfltr orch, grant the session tools only if you want it to use them itself: --hub-tools Read,Grep.

Exit status of nfltr orch "<goal>"

For scripts: 0 the session ran to its end; 1 the hub could not start (key rejected, relay unreachable, its tools did not come up) or claude failed; 3 an agent of this session ended budget_exceeded. The answer itself is not judged and its text never sets the status: a hub that ends with a question in its answer exits 0; to keep a question open until you answer, the hub uses an owner request, which keeps the session open.

The spend line

nfltr orch ends with spend: this session: hub $X, agents …; this hub id, all sessions: agents …. The first part is this session; the second is every session of the hub id. at least $X or cost unknown means the hub session was stopped (for example by SIGTERM) before Claude reported its last turn's cost; the line after received … at … says which signal and when.

"hub … is already open by pid …"

Why: only one live process may hold a hub id, and a second session in the same project resolves the same id. Fix: stop the other process, or give the second session its own --hub-id (in Claude Code: claude mcp add nfltr-review -- nfltr mcp --toolset hub --hub-id review). A lock left by a dead process is reclaimed automatically.

Credential and clean-config refusals

Recover

$ nfltr orch task status --task TASK_ID --events 20
$ nfltr orch task artifact list --task TASK_ID

Related: Join machines as nodes · Hub tools reference · Observe orchestration.