---
title: CLI errors
description: Every code the looot CLI's own error path can print, split into local (never left the machine), network, file and gateway-relayed codes.
sidebar:
  label: CLI
---

Every `looot` error goes through one path (`describeCliError` in the CLI source) and prints once,
in the [CLI stderr shape](/errors#cli-stderr): one line plus a fix in human mode, one JSON object
on stderr in `--format json`/`jsonl` mode, exit code 1. See [CLI command reference](/cli).

A code below marked **local** never reached the gateway: the command refused before sending a
request. A code marked **gateway** is the gateway's own code, described further on
[REST errors](/errors/rest-errors), [MCP errors](/errors/mcp-errors) or
[Run errors](/errors/run-errors); the entry here is only the CLI's fix text for it.

## Usage errors (local)

### token_required

No token is saved and none is set. Retryable: no. Fix: `looot login`, or set `LOOOT_TOKEN`.
Browsing (`search`, `inspect`, `catalog endpoints|search|list|inspect|compare`) works without one.

### endpoint_required

`looot run` was given no endpoint id, or the first argument after `run` looked like a flag.
Retryable: no. Fix: `looot run <endpoint-id> --input '{...}'`; `looot search "text"` lists ids.

### run_id_required

`looot runs get|cancel|attempts|evidence`, or `looot inspect`/`verify`, was given no id.
Retryable: no. Fix: `looot search` lists endpoint ids, `looot runs list` lists run ids.

### search_text_required

`looot search` got a flag as its first argument, where the search text belongs. Retryable: no. Fix:
put the text before any flag: `looot search "find a work email" --limit 5`.

### invalid_input_json

`--input` on `looot run` isn't valid JSON, or isn't a JSON object. Retryable: no. Fix: wrap the
JSON in single quotes: `--input '{"q":"text"}'`; `looot inspect <endpoint-id>` shows the fields.

### invalid_json

A JSON argument elsewhere (not `--input`) failed to parse. Retryable: no. Fix: check the quoting;
in a shell, wrap JSON in single quotes.

### validation_error

A local flag or file failed the CLI's own shape check, before anything was sent. Retryable: no.
Fix: the message names the field; fix it and run the command again. (The gateway's own
`validation_error`, for a request it did receive, is on
[REST errors](/errors/rest-errors#validation_error).)

### invalid_output_format

`--format` wasn't `json`, `jsonl` or `human`, or was given somewhere other than right after the
command. Retryable: no. Fix: put `--format` after the command, e.g. `looot balance --format json`.

### token_flag_unsupported

A `--token` flag was passed. There is no `--token` flag on purpose, so a secret never lands in
shell history. Retryable: no. Fix: `looot login`, or set `LOOOT_TOKEN`.

### unknown_command

The command, or a command's subcommand, isn't one `looot` has. Retryable: no. Fix: run
`looot help` for the list, or `looot help <command>` for one command's flags.

## Login errors (local, and the browser round trip)

### login_denied

`looot login` was approved as "Deny" in the browser. Retryable: no. Fix: if that was a mistake,
run `looot login` again and choose Approve.

### login_timeout

Login wasn't approved in the browser within 10 minutes. Retryable: yes. Fix: run `looot login`
again and approve it within the window.

### login_forbidden

The account that opened the approval page isn't an owner or admin of the organization.
Retryable: no. Fix: approve with an owner or admin account.

### login_rejected

The approval server rejected the login for a reason other than "not an owner/admin". Retryable:
no. Fix: run `looot login` again; a token passed with `--token-stdin` must be a current one from
`https://looot.ai/connect`.

### login_failed

The login flow failed before it could even reach the approval step. Retryable: no. Fix: run
`looot login` again.

## Config file errors (local)

### config_corrupt

`~/.config/looot/config.json` exists but isn't valid JSON or is missing required fields.
Retryable: no. Fix: delete it and run `looot login`.

### config_unreadable

`~/.config/looot/config.json` exists but couldn't be read (permissions, or it's a directory).
Retryable: no. Fix: check its permissions, or delete it and run `looot login`.

## Network errors (local; the request never got an answer)

### connection_refused

Nothing is listening at the gateway address. Retryable: yes. Fix: check `--url` or
`LOOOT_API_URL`; the public gateway is `https://api.looot.ai`.

### dns_failure

The gateway's hostname couldn't be resolved. Retryable: yes. Fix: check the address (`--url` or
`LOOOT_API_URL`) and your network connection.

### network_unreachable

There's no route to the gateway's host. Retryable: yes. Fix: check your network connection, VPN
or proxy, then run the command again.

### connection_reset

The connection to the gateway dropped mid-request. Retryable: yes. Fix: run the same command
again.

### tls_error

The gateway's TLS certificate wasn't accepted. Retryable: no. Fix: check `--url`
(`https://api.looot.ai`) and any proxy that intercepts TLS.

### network_error

A network failure that doesn't match one of the more specific codes above. Retryable: yes. Fix:
check your network connection and `--url`, then run the command again.

### gateway_timeout

The gateway didn't answer within the request timeout. Retryable: yes. Fix: run the same command
again; if the gateway stays silent, check `https://looot.ai/status`.

### invalid_url

`--url` or `LOOOT_API_URL` isn't a valid URL (for example, missing a scheme). Retryable: no. Fix:
use a full URL with a scheme, e.g. `https://api.looot.ai`.

### non_json_response

Something other than the looot gateway answered (a proxy's error page, a wrong `--url`).
Retryable: sometimes (a 5xx page is retried once automatically; a 4xx page is not). Fix: check
`--url`; retry in a moment if it was a 5xx.

### unexpected_response

The gateway answered, but not in a shape this CLI version expects (an old CLI against a newer
gateway, or `--url` pointed at another service). Retryable: no. Fix: check that `--url` (or
`LOOOT_API_URL`) points at `https://api.looot.ai`; if it does, `looot doctor` names the version
published on npm, so you can update.

## File errors (local)

### file_not_found

No such file or directory at the given path. Retryable: no. Fix: check the path; a relative path
starts from the current directory.

### permission_denied

The file exists but the CLI can't read or write it. Retryable: no. Fix: check the file's
permissions (`chmod 600` for a config file you own).

### read_only_filesystem

The CLI tried to write to a read-only filesystem. Retryable: no. Fix: point the command at a
writable location.

### is_a_directory

A path the CLI expected to be a file is a directory. Retryable: no. Fix: pass the path of a file
inside it.

### not_a_directory

Part of a given path isn't a directory. Retryable: no. Fix: check the path.

### file_exists

The CLI tried to create a file that's already there. Retryable: no. Fix: move or remove it, or
pick another path.

### disk_full

There's no space left to write. Retryable: no. Fix: free some disk space, then run the command
again.

### file_error

A filesystem error that doesn't match one of the codes above. Retryable: no. Fix: check the path
and its permissions.

## Gateway-relayed codes

These are the gateway's own codes, forwarded through the CLI's shape with the same `fix` text it
always has. [`insufficient_balance`](/errors/rest-errors#insufficient_balance), [`idempotency_conflict`](/errors/rest-errors#idempotency_conflict), [`too_many_inflight_runs`](/errors/rest-errors#too_many_inflight_runs),
[`catalog_loading`](/errors/rest-errors#catalog_loading) and [`storage_busy`](/errors/rest-errors#storage_busy) are documented on
[REST errors](/errors/rest-errors); [`provider_error`](/errors/run-errors#provider_error), [`provider_disabled`](/errors/run-errors#provider_disabled) and the rest of a
failed run's codes are on [Run errors](/errors/run-errors).

### unauthorized

The token is missing, expired or revoked (HTTP 401). Retryable: no. Fix: `looot login`, or set
`LOOOT_TOKEN` to a current token. An MCP client that signed in with the browser should reopen its
sign-in flow instead.

### forbidden

The token lacks the scope for this command (HTTP 403). Retryable: no. Fix: `looot whoami` lists
its scopes; an owner or admin can issue one with more.

## Anything else

### cli_error

A fallback for an error this path doesn't classify by name. Retryable: no. Fix: read the message;
report it with the command you ran if it looks like a bug.

## Ctrl+C

Ctrl+C prints `Cancelled.` and exits with code 130, not one of the codes above. During
`looot login`, nothing was saved. During `looot run`, the run may still finish if the request
already reached the gateway; `looot runs list` shows it.

<Related />
