ErrLookupBackground articles › "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained

"Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained

Invalid CLI argument errors — messages like "Unknown argument", "invalid value", "must be one of", "expected ... got ...", or "Invalid filter" — are thrown at the argument-parsing layer of a CLI before any real work runs. This article covers why these validators exist, the recurring triggers across libraries (typos, wrong separators, missing values, empty shell variables, dangling flags), and the general strategies for fixing and preventing them.

Distilled from 85 documented records across 35 repositories.

Background

Invalid-CLI-argument errors are produced at the very front door of a tool: the argument parser or an immediately-following validation pass rejects your invocation before a single unit of real work happens. That is their defining property across the family. Phabricator's PhutilArgumentUsageException aborts bin/mail send-test before doing anything; RuboCop raises IncorrectCopNameError during option validation; sglang's ServerArgs check fires during startup before any model loads; neon's storcon_cli FromStr impls fail during argument parsing, before any request reaches the storage controller. When you see this family, the invocation itself is wrong — no task failed, no data was touched.

The validators are deliberately strict because silently ignoring a bad flag is dangerous. ECC's auto-update parser refuses any token outside its five supported flags because a mistyped command could run a partial update. code-server refuses to start rather than silently dropping a malformed --vscode-option. Yeachan-Heo/oh-my-codex validates --keep-policy to prevent an unknown keep policy from breaking mission compilation later. The error you get is the cheap failure the authors chose over an expensive, confusing one downstream.

Under the hood the family shares a small set of parsing mechanics. Many validators are allowlists: a token must exactly match an enumerated vocabulary (deno's split-point kinds, neon's active/offline and active/essential/pause/stop, ECC's ito command list, freeCodeCamp's fuzzy-matched superblock and block names). Many are structural: the parser splits a value on a separator and requires the split to succeed — influxdb3's key=value tokens, Playwright's username:password, deno's @-separated package@version filters, Zed's user@distro split on the first '@'. Others are numeric range checks (career-ops' --limit 1..100 and --months 1..120, Phabricator's positive-integer priority, sglang's -1-or-positive sentinel) where a missing value becomes NaN or 0 and fails the check.

The caller-side experience varies by library. Some errors echo back your exact input and enumerate the accepted values in the message itself (fluentd's capability list, deno's dcore naming the flag and the parse failure, freeCodeCamp suggesting 'is that what you meant?'); others only point at --help (RuboCop's --show-cops, ECC's --help). Parsing conventions differ too: some parsers require the value attached with '=' (deno's dcore --inspect), while others consume the next argv token, which is exactly how a dangling flag at the end of the line or '--limit --json' swallows the wrong thing. Behavior on empty values, case sensitivity, and alias handling (career-ops normalizes and aliases hn but still rejects 'the-guardian') is library-specific — always check the record or --help for the exact contract.

Common causes

What usually fixes it

Documented occurrences

…and 65 more across the corpus — use search.

Honest provenance: generated on 2026-08-28 from AI-assisted analysis of the linked records. See how records are made.