Exit codes
The CLI maps HTTP status to a small set of stable exit codes. Conditional shell logic (bron tx get $id || handle "$?") and CI gating both rely on these.
These won’t shift across
0.x. New status codes get a new mapping; existing mappings stay put.
Error envelope
A 4xx / 5xx response prints to stderr in this shape:statusis the raw HTTP status (also reflected in the exit code).codeis a stable error-code slug (AMOUNT_BELOW_MIN,WITHDRAWAL_LIMIT_EXCEEDED,INVALID_KEY, …). Branch on this in scripts; not on the human message.idis the per-request correlation ID (headerCorrelation-Id). The Bron team can pull the exact ES log line for your call with this. Quote it when reporting issues. Programmatic surfaces — Go SDKAPIError.RequestID, MCP error payloadrequestId— expose the same value under those longer names.
Why a request ID matters
The frontend calls this the Error ID. Same value: it’s the per-request correlation ID generated server-side, attached to every log line for that request across every service it touches (public-api, the worker that picked it up, MPC signers, blockchain writer). Quoting it lets us reproduce the failure exactly:id alongside whatever request ID you generate yourself — when something goes wrong, the join across logs is trivial.
Common error codes
A small reference of the most-seen codes; the canonical list is on Errors.Idempotency contract
Everytx <type> / tx create call accepts --externalId <key>. Bron de-duplicates by (workspaceId, externalId):
- Same
externalId, same body → returns the previously-created transaction. No duplicate. Exit code0. - Same
externalId, different body → exit code6(conflict),code: EXTERNAL_ID_CONFLICT. - Without
externalId→ every retry is a brand-new transaction. Don’t do this on transaction-creation calls.
--externalId from something stable (task ID, request hash, timestamp + nonce); keep it in scope across retries.
Retry strategy
The CLI itself retries idempotent reads (GET) on transient 5xx with linear backoff up to 3 attempts; you don’t have to wrap reads in a retry loop. Writes are not retried automatically — that’s the caller’s responsibility (with --externalId so retries are safe).
If you hit 429 (RATE_LIMITED), respect the Retry-After header in the response. The CLI prints it as details.retryAfter.
Reporting an issue
When the error isn’t obviously self-inflicted (config / bad input):- Re-run with
--debugto capture envelope + ping + dial logs to stderr. - Note the
id:value from the error envelope. - File the issue at https://github.com/bronlabs/bron-cli/issues with: command (redact secrets), CLI version (
bron --version), error envelope,id,--debuglog if relevant.
