# Exit codes

Every `cademi` command ends with an exit code that tells scripts what happened without parsing the output. API errors map to a code by HTTP status, after the CLI's automatic retries.

## Codes

| Code | Meaning |
|---|---|
| `0` | Success. Also an operation that ended as `partially_succeeded` while a command waited for it, which prints a warning. `cademi config apply` is the exception: see code `1`. |
| `1` | Generic error: an operation that ended as `failed` or `canceled`, a `cademi config apply` whose operation did not end as `succeeded`, a wait that reached its time limit, a failed `cademi doctor` check, or a network error after the retries. |
| `2` | Invalid usage: an unknown command or flag, a wrong number of arguments, an invalid field or body, or a confirmation or other input that needs a terminal (pass `--yes`). |
| `3` | Authentication: the API returned `401`, no credential is configured, the profile's credentials are missing from the keychain, or the OAuth session can no longer be renewed. |
| `4` | Permission: the API returned `403`. |
| `5` | Not found: the API returned `404`. |
| `6` | Rejected: any other `4xx`, such as `409`, `410`, `412`, or `422`. `cademi config validate` also exits with `6` when the manifest is invalid. |
| `7` | Rate limited: the API returned `429`. |
| `8` | Server error: the API returned `5xx`. |
| `130` | Canceled: you pressed Ctrl-C or declined a confirmation. |

The CLI retries network errors and `429`, `500`, `502`, `503`, and `504` responses before giving up ([Commands](https://cademi.dev/cli/commands.md#writes-retries-and-idempotency)), so codes `7` and `8` usually mean that the retries were exhausted. A `429` exits with `7` right away when the API asks for a wait longer than 60 seconds or the error is `too_many_streams`, and other `5xx` statuses exit with `8` without a retry. What each status means for your integration is described in [Errors](https://cademi.dev/api/errors.md#what-to-do-for-each-class).

```sh
cademi products get prd_12 --json > product.json
case $? in
  0) echo "found" ;;
  5) echo "not found or outside the scope of the current credentials" ;;
  3|4) echo "check the credential with: cademi auth status" ;;
  *) echo "failed" ;;
esac
```

## Error output

Errors always go to standard error. By default, an API error prints the error `code` and message, each item of `details`, a hint for common codes, the wait time for `rate_limit_exceeded`, and the `request_id`.

With `--json`, `-o json`, or `--jq` on the command, errors print as JSON instead:

- An API error prints the API's error envelope as the API returned it, with `code`, `message`, `request_id`, and `details`. See [Errors](https://cademi.dev/api/errors.md).
- An error raised by the CLI itself uses the same shape on a single line, with the code `cli_error`:

```json
{"error":{"code":"cli_error","message":"no profile configured: run `cademi auth login` or set CADEMI_API_KEY"}}
```

- A cancellation prints nothing and exits with `130`.

Branch on `error.code`, never on the message, which follows the language of `CADEMI_LANG` or your system locale.
