---
title: "CLI exit codes"
description: "The exit codes of the lookio CLI and the API error codes behind each one, so a script can decide between retrying, fixing and stopping."
canonical: "https://lookio.app/docs/cli/exit-codes"
updated: "2026-10-24"
---

# CLI exit codes

A script can branch on the exit code without reading a message.

| Code | Meaning                                              | What to do                                  |
| ---- | ---------------------------------------------------- | ------------------------------------------- |
| `0`  | Success.                                             | Continue.                                   |
| `1`  | A server or network failure, or an unexpected one.   | Retry later. Report it if it persists.      |
| `2`  | Bad usage, or a request the API rejected as invalid. | Fix the command. Do not retry it unchanged. |
| `3`  | Authentication or permission failure.                | Sign in again, or ask for a wider scope.    |
| `4`  | Not found in this workspace.                         | Stop. The ID does not exist here.           |
| `5`  | Rate limited.                                        | Wait for `Retry-After`, then retry.         |
| `6`  | State conflict.                                      | Read the state, then decide.                |
| `7`  | Out of credits.                                      | Stop and tell a human. Do not retry.        |

A resource of another workspace gives `4`, the same as one that does not exist.

## How API errors map to exit codes

The CLI maps each API `error.code` like this.

| Exit code | API error codes                                                                                                                                                          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `1`       | `internal_error`, `service_unavailable`                                                                                                                                  |
| `2`       | `invalid_request`, `unknown_field`, `invalid_parameter`, `invalid_cursor`, `request_too_large`, `request_too_large_for_plan`, `method_not_allowed`                       |
| `3`       | `authentication_required`, `invalid_api_key`, `api_key_expired`, `api_key_revoked`, `insufficient_scope`, `feature_not_available`, `admin_required`, `permission_denied` |
| `4`       | `resource_not_found`                                                                                                                                                     |
| `5`       | `rate_limited`                                                                                                                                                           |
| `6`       | `conflict`, `assistant_has_no_resources`                                                                                                                                 |
| `7`       | `insufficient_credits`                                                                                                                                                   |

`insufficient_credits` has an exit code of its own, `7`, on purpose. A job that runs out of credits must stop and tell a human. Codes `1`, `2` and `5` all invite a retry or a fix, so none of them could say it. A `402` with an unknown code also gives `7`.

The CLI picks the exit code from the API's `error.code` first. When the code is one it does not know, it falls back to the HTTP status, so an error added later still gets a sensible exit code.

## Cancelled confirmations

When you answer "no" to a confirmation prompt, the command exits `0`: declining is not a failure.
