Skip to content

fix(cli): route unknown subcommands through the shared error envelope - #427

Merged
ankitranjan7 merged 1 commit into
mainfrom
fix/unknown-subcommand-envelope
Aug 23, 2026
Merged

ankitranjan7 merged 1 commit into
mainfrom
fix/unknown-subcommand-envelope

Conversation

@ankitranjan7

Copy link
Copy Markdown
Contributor

The problem

main is red. #421 and #424 each passed on their own branch; neither was run against the other.

× 'unknown subcommand' exits 2 with one stderr line and no envelope for humans
× 'unknown subcommand' renders a JSON envelope under --json
× renders a YAML envelope for -f yaml

#421 added a suggestion handler for unknown subcommands that calls console.error and sets process.exitCode directly. #424 built the shared envelope path that decides between human bytes and a machine envelope. Because #421's handler prints from inside the parser, it never reaches that path — so webcmd adapter list rest --json got human text instead of JSON, and the two paths spelled the same sentence differently (Valid webcmd adapter commands: vs help: valid subcommands for \webcmd adapter`:`).

What changed

  1. The namespace command:* handler throws a CommanderStructuralError instead of printing. handleProgramParseError already owns the human-vs-envelope choice, so --json and -f yaml now reach this failure like every other usage error.
  2. The error carries an UNKNOWN_COMMAND envelope with the suggestion's help body.
  3. New unknownSubcommandHelp() is the single source for that sentence, matching structuralHelpText() in command-surface.ts. One wording, not two.
  4. Three tests updated to the new wording, and two updated to render through handleProgramParseError rather than expecting the parser to print.

Before / After

# BEFORE (main) — --json ignored
$ webcmd adapter list rest --json
error: unknown command 'list'
Did you mean: webcmd adapter status
Valid webcmd adapter commands: override, path, reset, source, status

# AFTER
$ webcmd adapter list rest
error: unknown command 'list'
Did you mean: webcmd adapter status
help: valid subcommands for `webcmd adapter`: override, path, reset, source, status

$ webcmd adapter list rest --json
{
  "ok": false,
  "error": {
    "code": "UNKNOWN_COMMAND",
    "message": "unknown command 'list'",
    "help": "valid subcommands for `webcmd adapter`: override, path, reset, source, status",
    "exitCode": 2
  }
}

Both exit 2. #421's suggestion survives; #424's envelope now fires.

Tests

npm run typecheck clean. npx vitest run --project unit — 155 files, 2732 passed, 1 skipped, 0 failed (was 3 failed on main).

🤖 Generated with Claude Code

#421 and #424 each passed alone and collide on main. #421's namespace
handler printed its suggestion with console.error and set exitCode, so it
never reached the envelope path #424 built: `--json` got human text and the
`help:` line was spelled two different ways.

The handler now throws a CommanderStructuralError carrying both the human
bytes and the envelope, and both paths use one wording for the help line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🟠 Maintainer review suggested — low confidence

The automated review could not reach a fully supported conclusion.

Limitations

  • The automated review returned an invalid structured result.

This review is advisory and does not block merging.

@ankitranjan7
ankitranjan7 merged commit 717c80a into main Aug 23, 2026
36 checks passed
@ankitranjan7
ankitranjan7 deleted the fix/unknown-subcommand-envelope branch August 23, 2026 15:55
ankitranjan7 pushed a commit that referenced this pull request Aug 23, 2026
…ist (#428)

Cloud's parity suite caught two ways hosted mode drifted from local after
#424/#427.

Hosted still passed includeCapturedStderrForUnknownOption, so it replayed
Commander's captured stderr on top of the line structuralErrorFromCommander
now formats itself, printing `error: unknown option ...` twice.

The `help:` subcommand list also differed: local used declaration order and
included Commander's auto `help` entry, hosted used manifest order without
it. Both are sorted and drop `help` now, leaving only commands hosted mode
genuinely cannot run (LOCAL strategy) as a difference.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant