Skip to main content

Errors and exit codes

Use this page when a command or a tool refuses and you want to know why and what to do next, or when a script needs to branch on the result. Every error has a code, and on the CLI each code has its own exit status.

Reading an error​

  1. At a terminal, an error is one line on stderr: error(<code>): <message>. The message says what to do.

    error(gated): APP-4 is queued behind APP-1, awaiting approval by VP. Pick a different task — approval is a human action, not a retry.
  2. With --json, the same error is one JSON object on stderr. The MCP server returns the same object in an isError result.

    {"code":"out_of_order","message":"APP-4 is later in the queue than APP-5, which is ready. Take APP-5, or ask a human to reorder or override.","detail":{"policy":"strict","expected":["APP-5"],"position":2,"expectedPosition":1},"retryable":false}
  3. Check retryable. Only revision_conflict, timeout, rate_limited, unavailable and offline are worth trying again; retrying anything else gives the same answer.

  4. In a script, branch on the exit status ($?) rather than parsing the message.

Exit codes​

ExitCodeWhat it meansWhat to do
0It worked
1unknownSomething failed that staple has no code for, or staple doctor found a failing checkRead the message; staple doctor prints the fix for a failing check
2validationThe input is wrong: an unknown flag, kind, status or setting value, a bad duration. A preview that needs --yes (for example install, add, config home --move, budget setup, budget forget) also exits 2 and changes nothingFix the input the message names, or add --yes after reading the preview
3not_foundNo such ticket, document, workspace, run or readingCheck the reference with staple ls or staple hub, or pass --ws
4conflictSomeone else got there first: the ticket is claimed, its status does not allow the move, or it still has unresolved blockersPick a different ticket. Do not retry
5duplicateAn open ticket with this title already exists under the same parent, or the status or kind already existsUse the existing one, or pass --allow-duplicate to staple new
6cycleThe blockers you set would make tickets wait on each other in a loopRemove one of the blockers
7revision_conflictSomeone changed the document, queue or milestone order since you read it (--base N)Read it again, merge your change, and retry
8timeoutstaple wait ran out of time; nothing failedWait again with a longer --timeout
9gatedThe ticket is held by an approval gate above itPick a different ticket. The gate's owner runs staple approve
10out_of_orderqueue.policy is strict and the pickup queue puts another ticket firstTake the ticket in detail.expected, or a person uses checkout --override -m <why>

These come only from cloud sync (staple cloud … and staple hub registry …):

ExitCodeWhat it meansWhat to do
11authThe credential is missing or invalidConnect again with staple cloud connect
12forbiddenThis machine is not a member, or a consent is missing (backups need staple cloud backup enable)Use the right token, or give the consent the message names
13revokedThis machine was revokedConnect again with a new token
14epoch_changedThe repository was restored again while this machine was catching up with itRun staple cloud sync again once nobody is restoring
15cursor_invalidThis machine's sync position belongs to another repository or cannot be readRun staple doctor. A workspace copied from another one needs staple cloud fork-id
16payload_too_largeA change is bigger than the service acceptsShorten the description, comment or document the message names
17schema_aheadAnother machine wrote data with a newer stapleUpgrade staple on this machine
18protocol_unsupportedThis staple and the service have no version in commonUpgrade staple, or the service
19rate_limitedThe service asked you to slow down; detail.retryAfter says how longTry again after that
20unavailableA passing failure on the serviceTry again later
21offlineThe service could not be reached. Local work carries onTry again when you are online

Retrying in a script​

Retry only on 19, 20 and 21. Do not use a range such as -ge 19: statuses above 21 are not staple's. The installed launcher exits 70 when no runtime is installed (run staple install --yes), and a signal gives 128 plus its number (130 for Ctrl-C). A loop that retried on those would never stop.

staple cloud sync
case $? in
19|20|21) echo "try again later" ;;
esac

Going deeper: the CLI in detail covers the error object's fields, and the sync design the cloud codes.