> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bronto.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Exit codes and errors

> The exit-code contract, the JSON error envelope, and which error code maps to which exit status.

## Exit codes

| Code | Meaning | Retry? |
| - | - | - |
| `0` | success | |
| `1` | unexpected or unclassified error, including API errors that aren't auth, not-found, or rate limits | sometimes; check `retryable` |
| `2` | usage or config error: bad flags or arguments, missing dataset, invalid config | no, fix the command |
| `3` | auth error: missing, invalid, or under-privileged API key | no, fix the credentials |
| `4` | not found | no |
| `5` | rate limited or timed out | yes for reads and rate limits; after a timed-out write, check whether it landed first |
| `130` | interrupted by Ctrl-C or SIGTERM | |

Long-running commands such as `bronto tail` and `bronto send` also exit `130` when you stop
them. If `send` can't deliver its last batch after the interrupt, it reports that error
and exits with its code instead.

When `bronto` runs an [exec plugin](https://docs.bronto.io/cli/extend/plugins.md), the plugin's own exit code passes
through unchanged.

The exit code comes from the error code's prefix or suffix:

* `usage_*` and `config_*` exit `2`.
* `auth_*` exits `3`.
* `*_not_found` exits `4`.
* `rate_limited` and `timeout` exit `5`.
* Everything else exits `1`.

An unfinished query is a `usage_invalid_query` error, so it exits `2`:

```console theme={"dark"}
$ bronto query check "status >= 500 AND" 2>/dev/null; echo "exit code $?"
exit code 2
```

## The error envelope

Errors always go to stderr. If stderr is a terminal, you get:

```
Error: incomplete expression — expected a condition (usage_invalid_query)
Hint:   status >= 500 AND
                   ^
```

If stderr isn't a terminal, you get one line of JSON instead:

```console theme={"dark"}
$ bronto query check "status >= 500 AND" 2>&1
{"error":{"code":"usage_invalid_query","hint":"  status \u003e= 500 AND\n                   ^","message":"incomplete expression — expected a condition","retryable":false}}
```

| Field | Always present | Meaning |
| - | - | - |
| `code` | yes | stable machine-readable error code (see below) |
| `message` | yes | human-readable description; don't parse it |
| `retryable` | yes | `true` when retrying the same command may succeed |
| `hint` | no | suggested fix, when there is one |

## Error codes

Every code `bronto` emits is listed below. Scripts should match on `code`.

| Code | Exit | When |
| - | - | - |
| `auth_invalid_key` | 3 | the API rejected the key (HTTP 401) |
| `auth_insufficient_role` | 3 | the key lacks permission (HTTP 403), often an ingestion-only key |
| `auth_missing_key` | 3 | no key from flag, environment, or keychain |
| `auth_status_not_ok` | 3 | `bronto auth status` found no usable key, or the API rejected it (401 or 403). Network and server failures keep their own code |
| `usage_missing_dataset` | 2 | several datasets and no `-d` or `default_dataset` |
| `usage_ambiguous_dataset` | 2 | a dataset name exists in more than one collection |
| `usage_ambiguous_<kind>` | 2 | a name matches several resources of that kind, for example `usage_ambiguous_monitor` or `usage_ambiguous_api_key`; pass the id instead |
| `usage_unknown_field`, `usage_ambiguous_field` | 2 | a filter flag names a field that doesn't exist or matches several |
| `usage_invalid_query` | 2 | the WHERE expression doesn't parse |
| `usage_invalid_dataset` | 2 | `bronto send -d` isn't `<dataset>` or `<collection>/<dataset>` |
| `usage_confirmation_required` | 2 | a destructive command ran without a terminal and without `--yes` |
| `usage_invalid_args` | 2 | wrong number of arguments, or an unknown command or subcommand |
| `usage_invalid_flag`, `usage_invalid_flags` | 2 | unknown flag, or flags that can't be combined |
| `usage_missing_flag` | 2 | a required flag, or one of a required group of flags, is missing |
| `usage_conflicting_flags` | 2 | mutually exclusive flags were combined, such as `--input` and `-f` |
| `usage_conflicting_time_flags`, `usage_invalid_time_flags` | 2 | `--since` combined with `--from`/`--to`, or an invalid `--from`/`--to` range |
| `usage_invalid_since` | 2 | a `--since` or `--window` value the command can't use |
| `usage_invalid_interval` | 2 | `bronto tail --interval` or `bronto send --flush-interval` is too short |
| `usage_invalid_dedup_size` | 2 | `bronto tail --dedup-size` isn't a positive integer |
| `usage_invalid_regex` | 2 | a regular expression doesn't compile |
| `usage_invalid_direction` | 2 | `bronto context --direction` isn't `before`, `after`, or `both` |
| `usage_invalid_limit` | 2 | a `-n`/`--limit` or REPL `\limit` value is out of range |
| `usage_invalid_window` | 2 | `bronto tail --window` isn't a single positive duration such as `30s` or `5m` |
| `usage_unknown_meta` | 2 | an unknown meta-command in `bronto repl` |
| `usage_invalid_kind`, `usage_invalid_attr` | 2 | `bronto traces` got an unknown span kind or an empty attribute name |
| `usage_min_traces_too_high` | 2 | no `bronto traces shape` bucket has `--min-traces` traces |
| `usage_invalid_output_format` | 2 | unknown `--output` format, or one the command can't produce |
| `usage_invalid_jq` | 2 | the `--jq` expression doesn't parse |
| `usage_invalid_field` | 2 | a `-f` value isn't `key=value`, has an empty key, or repeats a key |
| `usage_missing_body` | 2 | `create` or `update` got neither `--input` nor `-f` |
| `usage_invalid_body` | 2 | the `--input` body is empty or isn't a JSON object or array |
| `usage_input_file` | 2 | an input file can't be read, or isn't valid JSON |
| `usage_missing_fields` | 2 | an `update` that replaces the whole resource is missing required fields |
| `usage_invalid_method` | 2 | `bronto api` got an unsupported HTTP method |
| `usage_invalid_region` | 2 | `--region` isn't `eu` or `us` |
| `usage_invalid_tag` | 2 | a `bronto send --tag` isn't `key=value` with a non-empty key |
| `usage_missing_message` | 2 | an event sent with `bronto send` has no `message` field |
| `usage_missing_question` | 2 | `bronto ask` got an empty question |
| `usage_key_required` | 2 | `bronto auth login` without a terminal or `--key-stdin` |
| `usage_repl_requires_tty` | 2 | `bronto repl` with piped input or output |
| `config_ask_not_configured` | 2 | `bronto ask` without `ask_url` |
| `config_invalid_region` | 2 | region isn't a slug like `eu` |
| `config_invalid_timeout`, `config_invalid_max_retries` | 2 | `timeout` isn't a positive whole number of seconds, or `max_retries` isn't a whole number of 0 or more |
| `config_invalid_url` | 2 | a URL setting isn't an `http` or `https` URL, or `base_url` has a query string or fragment |
| `config_parse_error` | 2 | a config file isn't valid TOML |
| `config_secret_in_project_file`, `config_secret_in_config_file` | 2 | a config file contains `api_key` |
| `config_secret_rejected` | 2 | `bronto config set` was asked to store `api_key` or `ask_api_key` in the config file |
| `config_unknown_key` | 2 | `bronto config get` for a key with no value, or `bronto config set` for a key that isn't a setting |
| `resource_not_found` | 4 | the API returned 404, or no resource has that name |
| `dataset_not_found`, `trace_not_found`, `profile_not_found`, `org_not_found` | 4 | the named thing doesn't exist |
| `rate_limited` | 5 | the API returned 429 |
| `timeout` | 5 | the request timed out |
| `network_error` | 1 | the host couldn't be reached (retryable) |
| `api_server_error` | 1 | the API returned a 5xx (retryable) |
| `api_error` | 1 | any other API error status |
| `query_unknown_field` | 1 | `bronto query check --strict` found unknown fields |
| `monitor_check_failed` | 1 | `bronto monitors check` found problems |
| `forward_destination_failed` | 1 | `bronto forward-configs test` found that Bronto can't write to the S3 destination |
| `export_failed`, `export_wait_timeout` | 1 | an export job failed, or `--wait` gave up |
| `export_no_id`, `export_no_location` | 1 | an export response had no id or download location |
| `export_download_failed`, `export_download_insecure` | 1 | the `--download` URL returned an error, or isn't `https` |
| `saved_search_invalid` | 1 | `bronto search --saved` named a saved search with no query to run |
| `payload_too_large` | 1 | an ingestion batch was over 10 MB |
| `ingest_read_error` | 1 | `bronto send` couldn't read its input, for example a line over 1 MiB |
| `local_file_error` | 1 | `bronto search --local` couldn't open or read a local file |
| `plugin_exec_error` | 1 | an exec plugin was found but couldn't be started |
| `ask_llm_error` | 1 | the `bronto ask` endpoint failed or returned something unusable |
| `internal_output_misuse` | 1 | a bug in `bronto` itself; please report it |
| `unknown_error` | 1 | an error without a code |

Idempotent requests that get a 429, 502, 503, or 504 are retried automatically before an
error is reported, `--max-retries` times (default 2).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.