Skip to content

fix: reject duplicate flag names - #2396

Open
deepakganesh78 wants to merge 1 commit into
urfave:mainfrom
deepakganesh78:fix/issue2174-duplicate-flags
Open

fix: reject duplicate flag names#2396
deepakganesh78 wants to merge 1 commit into
urfave:mainfrom
deepakganesh78:fix/issue2174-duplicate-flags

Conversation

@deepakganesh78

@deepakganesh78 deepakganesh78 commented Aug 2, 2026

Copy link
Copy Markdown

What type of PR is this?

  • bug

What this PR does / why we need it:

  • Rejects genuine duplicate user-defined local flag names and aliases on a command, so ambiguous command configurations fail early.
  • Makes built-in help flag installation name-aware: if a user flag already claims help or h, the auto-added help flag is not appended.
  • Keeps the existing name-aware version flag behavior unchanged.

Before this change, a command with a user-defined &BoolFlag{Name: "help"} received the built-in help flag too, leaving two flags named help and duplicated help output. After this change, the user-defined help flag wins, overriding the help flag continues to work, --help still parses without error, and only one help flag is present.

Which issue(s) this PR fixes:

Fixes #2174

Special notes for your reviewer:

Compatibility note: user-defined overrides of the built-in help flag continue to work. Only configurations where the user's own Flags slice contains duplicate names/aliases now return an error during Run.

Testing

  • Regression checks: go test -run "TestDuplicateFlagNamesAreRejected|TestUserDefinedHelpFlagOverridesBuiltin" -count=1 -v fails on unmodified source (TestDuplicateFlagNamesAreRejected gets nil errors; TestUserDefinedHelpFlagOverridesBuiltin finds 2 help flags) and passes with this fix.
  • go build ./...
  • go vet ./...
  • gofmt -l . ✅ empty
  • go test ./...
  • go run ./scripts/build.go generate
  • go run ./scripts/build.go vet
  • go run ./scripts/build.go check-binary-size ✅ (1.8MB current size; target 1.5MB2.2MB)
  • go run ./scripts/build.go v3diff ✅ (with Git diff on PATH)

Release Notes

Reject command configurations with duplicate user-defined flag names or aliases.

@deepakganesh78
deepakganesh78 requested a review from a team as a code owner August 2, 2026 15:31
Detect duplicate local flag names and aliases after built-in defaults are added so ambiguous command configurations fail instead of rendering repeated flags or shadowing built-in help.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@deepakganesh78
deepakganesh78 force-pushed the fix/issue2174-duplicate-flags branch from 1c0774c to 44743e2 Compare August 2, 2026 15:35
@dearchap

Copy link
Copy Markdown
Contributor

Review: reject duplicate flag names

Verified the change against the base. Core behavior works, but there is one behavioral regression worth addressing before merge.

1. Moderate — a user-defined -h flag now silently disables --help

command_setup.go skips appending the built-in help flag whenever any of its names (help, h) is claimed. Unlike the version flag, no aliases are dropped, so claiming just -h kills --help entirely.

Repro with &BoolFlag{Name: "h", Usage: "custom host flag"}:

  • Before: foo --help shows help.
  • After: foo --help -> flag provided but not defined: -help.

This is inconsistent with the version-flag handling in the same file (from #2229), which applies dropClashingAliases so a user -v flag keeps --version working. A custom -h flag is a common pattern (e.g. -h for host), so this is a real, silent behavior change for existing users.

Suggested fix: mirror the version path — apply dropClashingAliases to the help flag aliases before the flagNamesInUse check. Then a user -h keeps --help working (with -h reclaimed by the user flag), and only a user flag named help suppresses the builtin.

2. Low — duplicates involving MutuallyExclusiveFlags are not caught

checkDuplicateFlagNames iterates cmd.Flags only, but mutually-exclusive flags are registered separately and parsed via allFlags()/lookupAppliedFlag. These pass with no error despite being genuine duplicate-name configs:

  • a flag in cmd.Flags colliding with one in MutuallyExclusiveFlags
  • two flags with the same name inside a mutual-exclusion group

This falls short of the PR's stated goal of rejecting duplicate user-defined local flag names. Iterating cmd.allFlags() instead would cover them without false positives (builtin help/version appends are already guarded against name clashes, and the name-map dedups repeated references to the same flag object).

3. Low — the check runs even with SkipFlagParsing: true

SkipFlagParsing: true + duplicate names now errors on Run, even though the user explicitly opted out of flag parsing. This may be intentional (duplicates still pollute help output), but it is a behavior change worth confirming.

Minor notes

  • The check runs only on commands in the executed path; duplicates in a subcommand surface only when that subcommand is invoked, not at root Run.
  • The error is returned before the OnUsageError/ExitErrHandler/"Incorrect Usage" machinery (consistent with the StopOnNthArg validation just below it), so it will not be routed through exit handlers.

Verified OK

  • No false positives from builtin help/version flags (appends are name-guarded; e.g. a user v/help flag does not trip the duplicate check).
  • Full test suite passes; new tests are solid; helper is unexported so there is no API-surface change.

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.

Repeated similarly named flags & Before() doesn't go before --help global option.

2 participants