Exit codes

rf uses five exit codes, and never overloads them.

Exit Class Meaning Retryable
0 success The operation ran. This includes an empty result (data: []). A conformance self-check with no failures also exits 0. No
1 user-input error Bad flags, a missing argument, an unknown verb, --structural without --lang, or a bad regex. Also a failing conformance self-check. No — fix the call
3 tool-environment error A missing or unusable engine dependency in the environment. No — fix the environment
5 conflict A paged result’s snapshot changed underneath the cursor. Restart the query with the emitted command. Yes — re-run
6 internal An internal defect caught by the totality wrapper. No — report it

Why empty is exit 0

A plain rg exits 1 when it finds nothing, which conflates “the term is not here” with “the search failed.” A caller cannot tell the two apart. rf splits them: a genuine empty result is exit 0 with ok: true and data: []; a broken call, environment, snapshot conflict, or internal fault gets a non-zero code (1, 3, 5, or 6) with data: null and a populated errors array. See the agent guide.

Error codes

When rf exits non-zero, errors[] carries a stable code. The complete set:

Code Meaning
USAGE Invalid arguments: unknown verb or flag, missing flag value, or --structural without --lang.
UNKNOWN_FLAG An unrecognized global or verb-local flag.
UNKNOWN_COMMAND An unrecognized command path.
MISSING_ARGUMENT A required positional or flag value is absent.
INVALID_INPUT A supplied value failed parser validation.
INVALID_SELECTION Selected-input bytes or paths failed validation.
BAD_PATTERN The search regex failed to compile.
CONFLICT A cursor snapshot no longer matches the current result set.
HISTORY_ERROR Git history could not be scanned; no partial result was returned.
CONFORMANCE_FAIL One or more conformance cases returned verdict fail.
INTERNAL An internal fault caught by the totality wrapper.

Warning codes

Warnings never change the exit code. Each recovered miss adds one entry to warnings[] as { code, files, msg }. The complete set:

Code Meaning
IGNORE_VCS Matches hidden by .gitignore/.ignore rules; add -u.
HIDDEN_SKIPPED Matches in hidden files/dotfiles skipped by default; add -uu.
BINARY_SKIPPED Matches in files detected as binary; add -uu -a.
CASE_SENSITIVE Matches a case-insensitive search would add; add -i.
ENCODING_MISS Matches found only under the UTF-16 encoding probe.
FD_NAME Files excluded by the fd name/extension filter.
FD_HIDDEN Files excluded because hidden (fd).
FD_IGNORE Files excluded by ignore rules (fd).
RG_BINARY Files skipped by ripgrep’s binary detection.
GIT_DELETED Matches recovered from Git history after removal from the tree.
GIT_ABSENT git is unavailable, so history was not scanned.
GIT_NOT_WORK_TREE The path is not inside a Git work tree; no history.
GIT_HISTORY_PARTIAL The history scan was incomplete (budget or failed revisions).
AST_STRUCTURAL Matches found only by ast-grep structural search.
STRUCTURAL_UNAVAILABLE Structural search was requested but ast-grep is unavailable.
IGNORE_MODE Reports the active ignore mode for the path.

Both tables are the curated view; rf capabilities --json is the authoritative source of the code sets.

It never crashes on you

There is one totality wrapper. A backend panic or internal defect becomes an error envelope with exit 6, and a tool-environment failure exits 3 — never an uncaught crash, and never a partial write to stdout. A missing external oracle (git, ast-grep) is a warning, not an error, so it never changes the exit code on its own.