Troubleshooting
Troubleshooting
This page lists the errors people meet most, grouped by what you were doing. Each one shows the exact lines the tool prints and what to do.
Before you start
The examples use the workspace billing from Your first relay. You are dana, its owner, and build-agent and review-agent are your agent handles. Where an example saves a baton, it uses the baton.md file from that page.
Each example shows one situation, and the line above it says what that situation is, such as work that another handle holds. The examples are not steps to run in order. To see one for yourself, set up its situation first.
How to read an error
Every error has two lines. The first line is for you: what happened and what to do. The second line is for an agent or a script. It starts with a code, such as held_by_other, and ends with the fix.
The tool's exit code says what kind of answer it was:
| Exit code | Meaning |
|---|---|
| 0 | Accepted, or done. |
| 1 | Refused by a rule. The work did not change, but its history may record the refused write. |
| 2 | The tool could not reach the service, could not tell, or you are not signed in. |
| 3 | Queued on this machine. The service has not accepted it yet. |
Signing in
You are not signed in
Here nobody has signed in on this machine yet:
handsoff whoami --server https://handsoff.run
Choose a signed-in account or sign in on this machine.
sign_in_required: no single account was selected; fix: run handsoff login, or use --account <subject> when several accounts are stored
Run handsoff login --server https://handsoff.run, as Sign in shows. Every command that needs the service gives the same two lines until you do. The tool does not queue a write when you are not signed in.
The same lines appear when you name a service other than the one you signed in to. Your sign-in belongs to one service address. Check --server and HANDSOFF_SERVER.
No service chosen
On a machine where the tool has never signed in, it does not know which service to use:
handsoff whoami
Choose the record to use; sign in with handsoff login --server <address>.
invalid: the requested operation needs correction; fix: run handsoff login --server <address>
Sign in with the service's address. The tool remembers it.
The address is wrong
If the tool cannot reach the address you gave, it says so. Here the address names a host that does not exist:
handsoff login --server https://relay.example.invalid --no-browser
The record could not be reached; check the server address, network access and this session's sandbox.
unavailable: the record or local state could not be reached; fix: check proxy settings, NO_PROXY, network access and the session's sandbox; retry
Check the address with whoever runs your Handsoff service. Copy it whole, with https://.
The tool refuses an address that does not start with https:// before it sends anything:
handsoff login --server http://relay.example --no-browser
The server address is not safe; use HTTPS or loopback HTTP without credentials.
invalid: the requested operation needs correction; fix: set --server to an HTTPS address or a loopback test server
Choosing a workspace and a handle
No workspace chosen
Here you are signed in, but you have not created or chosen a workspace yet:
handsoff list
Choose a workspace first; use handsoff workspace use <name>.
invalid: the requested operation needs correction; fix: run handsoff workspace use <name> or use --workspace <name>
Run handsoff workspace list to see your workspaces, then handsoff workspace use <name>. Or add --workspace <name> to the one command.
No handle chosen
Here the command names a workspace, but you gave no handle, and the tool has no default handle yet:
handsoff list --workspace billing
Choose the handle to act as; set HANDSOFF_HANDLE or --as.
invalid: the requested operation needs correction; fix: set HANDSOFF_HANDLE or use --as <handle>
Add --as <handle>, or set HANDSOFF_HANDLE. When you create a workspace, your owner handle becomes the default. When you claim a handle on a machine with no workspace chosen, that handle becomes the default.
The workspace name is taken
Here a workspace called billing already exists on the service, yours or someone else's:
handsoff workspace create billing --owner-handle dana
This request cannot be used; check its fields and send it again.
invalid: the name, reference or related record is not usable; choose a new name or check the requested ids; fix: check the documented request fields and send it again
Everyone on the service shares one set of workspace names. Choose another name, such as your team's name. Workspaces says more.
The handle is unknown or disabled
Say you change something as a handle that does not exist, that the owner disabled, or that is not yours. Here the handle name has a typo:
handsoff open BILL-59 --title "Typo check" --as revew-agent --baton baton.md
This handle is disabled or belongs to someone else; choose your enabled handle.
not_your_handle: acting handle is not enabled and bound to this sign-in; fix: choose an enabled handle bound to your sign-in
When you only read, the same mistake gets this answer:
handsoff list --as nobody
This record is not available to this handle; check the workspace, work and handle.
not_found: no visible matching record; fix: check the workspace, work and acting handle
Check the spelling. Run handsoff handle list to see the handles. It marks each disabled one.
Catching work
Another carrier holds the work
Here build-agent holds BILL-51, and you try to catch it as review-agent:
handsoff continue BILL-51 --as review-agent
build-agent holds this work until 2026-10-05T04:42:45.601585+00:00; ask for an offer or wait for the lease.
held_by_other: no catchable offer or drop; fix: ask the carrier for an offer or wait for its lease
Only one carrier holds a piece of work at a time. Ask the carrier to offer it to you. If the carrier has stopped, its lease runs out at the time shown and the work drops. Then you can catch it.
The offer is for someone else
Here build-agent offered BILL-54 to review-agent, and you try to catch it as yourself, dana:
handsoff continue BILL-54
This offer waits for review-agent; ask that handle to catch it, or wait for its deadline.
offered_to_other: receiver review-agent; fix: ask the named receiver to catch it or wait for the offer deadline
If the offer names a handle of yours, catch it as that handle, here with --as review-agent. If not, wait for the deadline.
Your handle holds it in another session
Here build-agent holds BILL-61 in another session, such as an earlier Codex conversation, and you try to catch it from a new one:
handsoff continue BILL-61 --as build-agent
Your handle holds this work in another session; use --take-over.
invalid: the requested operation needs correction; fix: use handsoff continue --take-over, or wait for the lease to lapse
This happens when a new session of the same agent tries to pick up its own work. Add --take-over to move the hold into this session. The old session's leg ends.
No such work
Here no work called BILL-99 exists in the workspace:
handsoff continue BILL-99 --as review-agent
This record is not available to this handle; check the workspace, work and handle.
not_found: no visible matching record; fix: check the workspace, work and acting handle
Check the work's name and the workspace. Work in a workspace where you have no handle gets the same answer.
The offer expired
An expired offer is not an error. The work drops, and the handle it was for can still catch it. If the passer was still working when the offer expired, the catch starts with a warning. Here build-agent offered BILL-54 to review-agent with --deadline 1m, kept working, and the minute passed:
handsoff continue BILL-54 --as review-agent
Caught BILL-54 at r1 from build-agent via drop
Attention
DROPPED
Contact with build-agent was lost: offer expired at 2026-10-05T04:14:55.388432+00:00. Its last accepted save was r1 at 2026-10-05T04:13:54.73071+00:00. It may have done more than one step after that save, so every step of the next action, and any step the baton names as in flight, may already be done, not only the first. Before you do each of those steps, check its outcome through the references, even a step that looks safe to repeat: skip it if it was done, and do only the rest if it was partly done. If you cannot tell for a step, stop and block the work.
…
Do what the warning says. After an interruption explains it. If the passer had ended its leg clean, the catch shows only a short notice in its place. Here build-agent offered BILL-53 with --deadline 1m and ended its leg clean, and the minute passed:
handsoff continue BILL-53 --as review-agent
Caught BILL-53 at r1 from build-agent via drop
Attention
the offer from build-agent expired at 2026-10-05T04:13:39.892238+00:00; the passer had ended its leg clean
…
Saving and passing work
Your lease ran out
Here build-agent opened BILL-52 with --lease 1m and tried to save after the minute had passed:
handsoff save BILL-52 --as build-agent --baton baton.md
The baton is no longer this leg's: lease lapsed at 2026-10-05T04:13:39.010313+00:00; the write was not applied. Run handsoff continue 53 to take it back if allowed, or give the notes to the current carrier.
not_holder: leg 106; current leg 106; lease lapsed at 2026-10-05T04:13:39.010313+00:00; fix: run handsoff continue 53 if allowed, or give the notes to the current carrier
Your hold ended and the work dropped. The save was not applied, and the work's baton did not change. The history keeps the baton you sent, marked late and not accepted, so the next carrier can see it. A baton that fails the baton checks is not kept. The number in the message is the work's id. If nobody else caught the work, catch it back, then save again:
handsoff continue 53 --as build-agent
Caught BILL-52 at r1 from build-agent via drop
…
handsoff save BILL-52 --as build-agent --baton baton.md
accepted as r2
If someone else caught it, give them what you know in a note: handsoff note BILL-52 --text "...". To avoid this, save more often, or run handsoff renew between saves.
This session holds no leg of the work
Here build-agent holds BILL-51, and review-agent, which never caught it, tries to save:
handsoff save BILL-51 --as review-agent --baton baton.md
this session holds no leg of BILL-51; run `handsoff continue BILL-51` (or `--take-over` if your handle holds it in another session)
not_holder: the local session has no single matching leg; fix: run handsoff continue BILL-51; use --take-over for another session
You can save only work you caught or opened in this session. Catch it first with continue.
An offer is waiting
Here build-agent offered BILL-66 to review-agent and then tried to save:
handsoff save BILL-66 --as build-agent --baton baton.md
An offer is waiting; retract it or let it be caught before saving.
offer_waiting: waiting offer; fix: retract the offer or let it be caught
While your offer waits, you cannot save. Either leave the work for the receiver, or take the offer back and then save:
handsoff retract BILL-66 --as build-agent
Retracted offer for BILL-66; now held
handsoff save BILL-66 --as build-agent --baton baton.md
accepted as r2
The work name is already used
Here BILL-51 already exists in the workspace, and review-agent tries to open a new piece of work with that name:
handsoff open BILL-51 --title "Invoice totals check" --as review-agent --baton baton.md
This request cannot be used; check its fields and send it again.
invalid: the name, reference or related record is not usable; choose a new name or check the requested ids; fix: check the documented request fields and send it again
Each piece of work in a workspace has its own name. Pick a new one. To work on the existing one, catch it with continue.
A deadline or lease is out of range
Here build-agent holds BILL-53 and asks for an offer that waits only 30 seconds:
handsoff offer BILL-53 --as build-agent --to review-agent --deadline 30s
This request cannot be used; check its fields and send it again.
invalid: deadline_seconds must be from 60 to 604800 seconds; fix: check the documented request fields and send it again
An offer's deadline must be from one minute to seven days. A lease must be from one minute to 12 hours.
A content check refused the text
The tool refuses text that looks like a secret, a chat transcript, or a terminal escape code. It saves nothing. Here secret.md is a copy of baton.md with a key in its Traps part, as Security and privacy shows:
handsoff open BILL-50 --title "Archive copy" --as build-agent --baton secret.md
This field looks like a credential; name where the secret lives instead.
content_refused: field Traps, line 1, pattern cloud-access; DESIGN 2.5; fix: name where the secret lives instead; use --baton <file> or handsoff save <ref> --baton /dev/stdin <<'EOF' ... EOF (save without --baton also reads standard input), with Markdown containing these headings in order: ## True now, ## Next action (with Done when: <text>), ## Traps, ## Evidence, ## References
The agent line names the part of the baton and the line. Remove the secret and add a secret reference that says where it lives. For text that looks like a transcript, write a short summary instead. For a terminal escape code, remove it. The first line of each refusal says which of these it is. Security and privacy shows each check.
When the service cannot be reached
The tool queued your write
If the service does not answer, the tool keeps your write on this machine and exits with code 3. Here a proxy that does not answer stands in for a network outage, and BILL-51 is work that exists in the workspace:
HTTPS_PROXY=http://127.0.0.1:9 handsoff note BILL-51 --as build-agent --text "Copy paused at invoice 1200"
Queued as pending, not accepted: note on BILL-51 (write 6a177ab6eabf). The record could not be reached: The record could not be reached; the environment proxy http://127.0.0.1:9 may be refusing or unable to reach the network.. Nothing has changed in the record. This machine sends it when the record answers, within 24 hours; run handsoff sync to send it now, or handsoff pending to list it.
Nothing is lost. The next command that reaches the service sends it. To see what waits, and to send it now:
handsoff pending
Pending on this machine, not accepted by the record: 1 queued, 0 refused, 0 conflict, 0 unsent; run handsoff pending.
6a177ab6eabf 2026-10-05T04:29:23Z (age 1s): note on BILL-51: pending
handsoff sync
Sent from the queue: note on BILL-51 accepted.
Queue replay complete; run handsoff pending for anything not accepted.
The service checks a queued write only when it gets it. So the work must exist for the note to be accepted. Here a note on BILL-98, which does not exist, was queued the same way. sync sends it, and the service refuses it:
handsoff sync
Pending on this machine, not accepted by the record: 0 queued, 1 refused, 0 conflict, 0 unsent; run handsoff pending.
Refused from the queue: note on BILL-98: not_found: This record is not available to this handle; check the workspace, work and handle.
Queue replay complete; run handsoff pending for anything not accepted.
handsoff pending discard 6692fbf420da
Pending on this machine, not accepted by the record: 0 queued, 1 refused, 0 conflict, 0 unsent; run handsoff pending.
Discarded note on BILL-98 (write 6692fbf420da).
A refused entry stays in handsoff pending until you discard it. The tool never sends it again by itself.
The service has not accepted a queued write yet. Do not tell anyone the work is saved until the tool says accepted. After 24 hours the tool stops sending it. Working offline explains the queue.
Proxy settings
If you reach the internet through a proxy, the tool uses HTTPS_PROXY, or ALL_PROXY when HTTPS_PROXY is empty. When the tool cannot reach the proxy, or the proxy refuses, the tool names it:
HTTPS_PROXY=http://127.0.0.1:9 handsoff whoami
The record could not be reached; the environment proxy http://127.0.0.1:9 may be refusing or unable to reach the network.
unavailable: the record or local state could not be reached; fix: check proxy settings, NO_PROXY, network access and the session's sandbox; retry
Check these:
HTTPS_PROXYorhttps_proxyholds the right proxy address. If you set both, the capital one wins.NO_PROXYorno_proxylists the hosts that skip the proxy, split by commas. A name there also covers the hosts under it.- An agent in a sandbox may have no network at all. Codex shows the sandbox settings it needs.
The tool never follows a redirect, and it waits up to five seconds for an answer.