Skip to content
Image KB Reducer
Esc
↑↓navigate↵open⌘Jpreview
On this page

Exit codes

Every code this tool can exit with, and what causes it.

Every usage mistake, refusal, and engine failure has its own exit code — never a generic non-zero “something went wrong.” With several inputs, the process exits with the first failure’s code, in input order; the --json envelope still carries every file’s own exitCode, so a script processing a batch doesn’t have to guess which file caused the process exit it observed.

This table is generated from — and kept in sync with, by a CI test — the EXIT map in this package’s own source (packages/cli/src/exit-codes.ts). If this page and that file ever disagree, the file is right and this page has a bug.

Code Name Meaning
0 OK every input succeeded (or --accept-closest wrote the closest file)
1 INTERNAL unexpected internal error — an engine failure this CLI has no story for
2 USAGE unknown command/flag, a required flag missing, a flag value that failed validation, strip on webp without --reencode or on heic at all, info given --out/--in-place/--dry-run
3 NOT_FOUND an input path doesn’t exist, or a glob matched nothing
4 WOULD_OVERWRITE the computed output already exists and isn’t the input (--force, --out, or --suffix all sidestep it; --in-place is the only way to target the input itself), or the output would land on a different file this same run was also asked to read — which --force does not sidestep, see Output files
10 FIXED_DIMENSIONS target-unreachable: the quality floor is still over target and --no-downscale pinned the dimensions. Offered hint: allow resizing (drop --no-downscale).
11 MIN_DIMENSION target-unreachable: downscaling was allowed, but the next step would go below the minimum dimension the search will accept.
12 FORMAT_FLOOR target-unreachable: out of downscale room, or shrinking stopped buying bytes — this format’s own entropy/header floor is above the target. Offered hint: try --format webp.
13 BUDGET_EXHAUSTED target-unreachable: ran out of encode attempts before finding anything under target. A soft failure — nothing is structurally impossible, the search just needs a higher --max-encodes on the next run.
20 UNSUPPORTED_FORMAT input isn’t jpeg/png/webp/heic (a renamed SVG, GIF, BMP, or anything else); also an avif strip --reencode target, since this backend bundles no AVIF encoder
21 DECODE_FAILED truncated/corrupt bytes that passed magic-byte sniffing, or an empty (0-byte) file
22 INPUT_TOO_LARGE input exceeds the configured byte ceiling — checked against stat().size before the file is read into memory
23 DIMENSION_EXCEEDED decoded (or requested output) dimensions exceed the configured pixel ceiling
24 ENCODE_FAILED encoder failed to produce output for the requested format/quality
25 INVALID_OP a requested operation couldn’t be applied after clamping was already attempted (e.g. a crop rect genuinely outside the source’s bounds)

10–13 are one family: target-unreachable

Codes 10 through 13 all come from the same engine error, target-unreachable — they’re not four unrelated failures, they’re the four reasons the byte-target search can give up, each carrying its own most-useful next step. Per the project’s own framing: this is a negotiation, not a crash. The stderr sentence for any of these four names both the closest size the search actually reached and the specific flag that would help — never a generic “couldn’t compress this.”

--accept-closest turns any of the four into exit 0: it writes the closest file the search found instead of failing, and says so on stderr.

Only compress always has a byte target and so can hit any of 10–13 on every run. resize and convert can hit them only when --to was given. crop, rotate, strip, and info never take a --to flag and can never produce these four codes at all.

Codes that exist but this CLI can never produce

The engine’s ErrorCode type also includes encode-format-mismatch and no-canvas-surface — both are canvas-backend-only failures (a browser <canvas> silently returning the wrong blob.type; no OffscreenCanvas/document available to draw on). This CLI runs entirely on the wasm backend, not the canvas one, so neither can ever occur here; there is deliberately no exit code reserved for either. An engine failure this CLI genuinely has no story for falls back to 1 (INTERNAL), never a fabricated specific-looking number.

Was this page helpful?