[Bug]: -f with an unknown format silently renders a table instead of failing
- Dominant language
- JavaScript
- Stars
- 29.5k
- Forks
- 2.9k
- Avg merge
- 15h 36m
- Merged PRs (30d)
- 70
Description
### Description
`-f/--format` accepts any string. An unrecognised value is not rejected: `render()` falls through to the `default:` branch of its switch and prints a table, exit code 0. A script or an agent that asks for a format it believes exists gets tabular output with box-drawing characters and no indication that its request was ignored.
The closed set is advertised. `--help` prints `choices: table, plain, json, yaml, md, csv`, and that list is declared in `COMMON_OPTIONS` in `src/help.js`. Nothing enforces it.
The inconsistency is internal to the same option table: `--trace`, declared with `choices` in the same block, *is* enforced — by an explicit normaliser that throws `ArgumentError`, alongside `normalizeSiteSession`, `normalizeBooleanOption` and `normalizeWindowMode` in `src/execution.js`. `--format` has no equivalent.
This bites agents hardest, because the wrong output is still parseable-looking text rather than an error.
### Steps to Reproduce
Reproduces on a core command, so it is not adapter-specific:
```console
$ opencli list -f bogus
opencli/list
┌───────────────────────────────────┬───────────────────┬─── ... (a table)
$ echo $?
0
$ opencli list -f csv # for contrast
command,site,name,aliases,description,access,strategy,browser,args
...
$ echo $?
0
```
Same on an adapter command, and next to `--trace` for comparison:
```console
$ opencli eur-lex get 32024R1689 --chars 10 -f bogus
eur-lex/get
┌────────────┬────────────────┬──── ... (a table, exit 0)
$ opencli eur-lex get 32024R1689 --chars 10 --trace bogus
ok: false
error:
code: ARGUMENT
message: '--trace must be one of: off, on, retain-on-failure. Received: "bogus"'
exitCode: 2
```
### Expected Behavior
`-f bogus` should fail the way `--trace bogus` already does: `ArgumentError`, exit 2, and a message naming the accepted values — `--format must be one of: table, plain, json, yaml, md, csv. Received: "bogus"`.
The list already exists in `COMMON_OPTIONS`, so the fix can reuse it rather than restate it, which also keeps `--help` and the validation from drifting apart.
Two adjacent notes, both smaller than the above:
1. `render()` also silently downgrades `table` to `yaml` when stdout is not a TTY. That behaviour is reasonable and documented in the code, but it means `footerExtra` disappears in every pipe — so an answer-level value put in the footer is unreachable to any non-interactive caller. Adapters can work around it by making the value a column; worth knowing when writing the guidance for adapter authors.
2. **Feature, separable from the bug:** `jsonl` would be a welcome seventh format — one JSON object per line, no enclosing array. It is the natural shape for streaming into `jq`, `duckdb read_ndjson_auto`, or a line-oriented pipeline, and today it needs `-f json | jq -c '.[]'`, which buffers the whole array first. `renderJsonl` is a four-line neighbour of `renderCsv`. Happy to open it as its own feature request if you would rather keep this issue to the bug.
### OpenCLI Version
1.8.7
### Environment
- Node.js v24.18.0
- Linux (WSL2), zsh
Contributor guide
Research direction
Start in src/help.js with COMMON_OPTIONS to find the declared format choices, then inspect render() and the option normalisers in src/execution.js, especially the existing --trace validation. Reuse the format choices so --format bogus raises ArgumentError with exit code 2 and the accepted values, while valid formats retain their current behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100