Skip to content

fix(cli): keep the --help hint on an unknown command - #45

Merged
thanhleviet merged 2 commits into
mainfrom
fix/keep-unknown-command-hint
Aug 5, 2026
Merged

thanhleviet merged 2 commits into
mainfrom
fix/keep-unknown-command-hint

Conversation

@thanhleviet

Copy link
Copy Markdown
Collaborator

Fixes a regression I introduced in v0.21.1.

What broke

v0.21.1 stopped every error printing twice by setting SilenceErrors on the root command and having main print the error instead. Cobra writes the unknown-command hint from the same branch as the error line:

// cobra@v1.10.2 command.go:1130
if !c.SilenceErrors {
    c.PrintErrln(c.ErrPrefix(), err.Error())
    c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath())
}

Both lines are gated on SilenceErrors alone, not on SilenceUsage. Silencing the duplicate silenced the hint with it, and main only reproduced the error line.

$ atb quer          # v0.21.1
Error: unknown command "quer" for "atb"

Did you mean this?
	query
                              <-- "Run 'atb --help' for usage." missing

The Did you mean this? suggestions were never affected; they are part of err.Error().

The fix

Cobra reports the error again and main only turns a failure into an exit code. SilenceErrors is removed from both root builders and run loses its writer parameter.

The reason v0.21.1 routed the print through main was to keep the error below the background update notice. That does not hold up:

  • CheckInBackground is called from PersistentPreRun, which never runs when argument parsing fails, so WaitForUpdateCheck is nil on exactly these paths.
  • In its cached branch printUpdateNotice runs inside PersistentPreRun, before the command body, so the notice is already above any command output.
  • Only the uncached branch prints from a goroutine, and that can interleave with any output, not just errors.

Output now matches v0.21.0 minus the duplicate:

$ atb quer
Error: unknown command "quer" for "atb"

Did you mean this?
	query

Run 'atb --help' for usage.

Tests

TestRunKeepsTheUnknownCommandHint was written first and failed on the missing hint while already asserting the error appeared once, so it pins both halves and cannot be satisfied by reverting v0.21.1.

The three existing tests carry over unchanged apart from the signature. TestRunPrefixesTheError still passes because cobra's ErrPrefix() is Error:.

Verification

  • Suite green, 22 packages; go vet clean; gofmt clean on the touched files; make docs no diff.
  • frobnicate, quer, dowload, sumarise, query --no-such-flag, columns --show nope each print the error once, exit 1, and unknown commands carry the hint.
  • --help, columns byte-identical to the published v0.21.1 binary on both streams; version differs only in the version string and Go toolchain, as expected for a local build.

@thanhleviet
thanhleviet merged commit 4c77c14 into main Aug 5, 2026
6 checks passed
@thanhleviet
thanhleviet deleted the fix/keep-unknown-command-hint branch August 5, 2026 16:46
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