Skip to content
Build with Mammoth: open the docs menu

Mammoth errors and exit codes

How failures are reported, which of them are worth retrying, and which are a bug in the request.

Read the envelope, not the text

In machine output the CLI writes a versioned envelope. Success goes to stdout; errors go to stderr. Branch on the exit code and the stable error.code, never on the human-readable message.

Success, stdout:

{"schema_version": 1, "data": "<result>", "meta": {"command": "…", "profile": "default", "workspace_id": 4, "project_id": 180}}

meta carries only the keys that have a value. It adds pagination on a paged read, and update_available ({"current", "latest", "command"}) when a newer CLI release exists. The CLI checks once a day, after a command, and never blocks on it. It installs a newer release by itself only in an interactive terminal; in CI, in a pipe or in an agent run it only reports update_available. MAMMOTH_AUTO_UPGRADE=1 forces the install on, and MAMMOTH_NO_UPDATE_CHECK=1 turns the check off.

A write returns what it did

Every command that changes something adds two blocks to data. Read them before you build on the change.

  • verify is the CLI's own verdict: verified (true or false), a state, any warnings, a reason when it is not verified, and needs_user. When needs_user is set, stop and tell a person before the next step. A row-changing step also carries rows_before and rows_after.
  • outcome is settled, pending, partial or failed. The envelope's top-level status follows the last three: partial exits 3, and failed exits 1 even though the API call itself went through (verify.reported_status keeps the earlier word).
  • A write still running when the wait ends reports status: pending and verify.next_command (mammoth view pipeline wait VIEW_ID, or mammoth job wait ID for an automation). It exits 0: the change was accepted, so wait on it and never replay it.
  • state is a fresh read of what the write produced, taken after it settled, not echoed from your request. If that read fails, state says unreadable and verify.verified becomes false.

A success envelope proves the call went through. The state block shows the outcome.

Error, stderr:

{"schema_version": 1, "error": {"code": "…", "message": "…", "summary": "…", "hint": "…", "details": {}, "request_id": null, "retryable": false, "authorization_required": false, "recovery_commands": ["…"], "log_ref": {"file": "…", "run_id": "…"}}}

summary is a plain-language sentence you can show a person. log_ref points at the local run log: mammoth log tail --input '{"run_id": "RUN_ID"}' lists every request that run made, with its HTTP status and the backend request_id. Quote both when you report a backend fault.

schema_version is a compatibility contract. It is 1 today and increments only on a breaking change to the envelope shape. Check it if you parse envelopes across CLI upgrades.

Exit codes

CodeMeaningRetry?
0Successn/a
1API errorno
2Usage, input, or confirmation failureno
3Partial: a write whose read-back shows only part of it took effectno
4Authentication failureno
5Not foundno
6Conflict, including file_exists when an export would overwrite a local fileno
7Retryable (network or timeout)yes
130Interruptedno

A timeout, exit code 7 or an interruption does not prove a write failed. When details.operation_state is outcome_unknown, the change may have committed: reconcile it with mammoth job get or a read of the resource before you replay it.

Exit 3 is not a transport failure. Read verify to see which part of the write took effect, finish or undo it, and do not replay the whole command.

Commands the server does not offer yet

The data-app commands and schedule create fail at once with the error code feature_unavailable and send no request. They do not appear in mammoth schema find.

Local checks

view transform extract-date, date-diff, increment-date and math check column types before any request. A TEXT column is refused with column_type_mismatch, and the error names the convert-type command to run first. An unexpected fault in the CLI itself is reported as internal_error; rerun with --debug for the stack trace.

A command that writes a local file (view export csv, dashboard bi-export, explore-panel export-image, support template export) refuses an existing file with file_exists (exit 6) unless you pass --overwrite.

Confirmation failures

A mutation that needs a confirmation and does not get one fails with exit code 2 and an error code of confirmation_required or confirmation_target_mismatch. It never proceeds and never prompts off a terminal. The rule is the same everywhere: an action that cannot be undone needs --yes, and a confirm_target command also needs --confirm ID with the exact target id. The CLI checks --confirm before it makes any API call.

On the HTTP side

Calling the API directly, a bad or missing credential returns 401; an authenticated caller without permission gets 403. The Python SDK raises MammothAuthError for the first.

Measured across all 471 operations in the v2 spec, the responses you will in fact meet are 400 (declared on 463), 403 (275), 404 (50), 202 (82, an async job), 422 (6) and 409 on exactly two. Those two are worth special handling: a 409 means you tried to delete a parameter or snippet that is still referenced, and it is the case a user most needs a clear message for.

Rate limits

Limits are per HTTP method and they apply to every caller, not only to paid tiers.

MethodRequests per minute
GET600
POST300
PATCH60
DELETE60

A fixed one-minute window, counted in Redis, keyed on your session when authenticated and on the caller IP when not. That last detail matters if you are embedding: anonymous dashboard viewers share a limit by IP.

The business error object

Some endpoints carry a richer error inside the transport envelope. It is real in the implementation but not discoverable from the spec, so expect the Litestar envelope at the transport level and look for the business error within it. Do not write a client that expects the business object as the top-level body.

Next up

Report an issue · support@mammoth.io