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.
verifyis the CLI's own verdict:verified(true or false), astate, anywarnings, areasonwhen it is not verified, andneeds_user. Whenneeds_useris set, stop and tell a person before the next step. A row-changing step also carriesrows_beforeandrows_after.outcomeissettled,pending,partialorfailed. The envelope's top-levelstatusfollows the last three:partialexits 3, andfailedexits 1 even though the API call itself went through (verify.reported_statuskeeps the earlier word).- A write still running when the wait ends reports
status: pendingandverify.next_command(mammoth view pipeline wait VIEW_ID, ormammoth job wait IDfor an automation). It exits 0: the change was accepted, so wait on it and never replay it. stateis a fresh read of what the write produced, taken after it settled, not echoed from your request. If that read fails,statesaysunreadableandverify.verifiedbecomes 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
| Code | Meaning | Retry? |
|---|---|---|
| 0 | Success | n/a |
| 1 | API error | no |
| 2 | Usage, input, or confirmation failure | no |
| 3 | Partial: a write whose read-back shows only part of it took effect | no |
| 4 | Authentication failure | no |
| 5 | Not found | no |
| 6 | Conflict, including file_exists when an export would overwrite a local file | no |
| 7 | Retryable (network or timeout) | yes |
| 130 | Interrupted | no |
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.
| Method | Requests per minute |
|---|---|
GET | 600 |
POST | 300 |
PATCH | 60 |
DELETE | 60 |
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
- Agents and CI—the reliable operation loop, end to end.
- Blast radius and safety—what each command will demand before it runs.