Skip to content

Fix env var validation conflicts#619

Merged
alecthomas merged 3 commits into
alecthomas:masterfrom
hindessm:mrh/env-var-conflicts
Jul 11, 2026
Merged

Fix env var validation conflicts#619
alecthomas merged 3 commits into
alecthomas:masterfrom
hindessm:mrh/env-var-conflicts

Conversation

@hindessm

@hindessm hindessm commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Environment variables with matching names on two commands with the same parent were validated against the requirements of both commands.

Caused by Reset() and Validate() walking the entire tree rather than only the nodes on the selected path.

Note that, this changes some error behaviour slightly. For example, if a default value was not a member of an enum set the validation would always catch this even if the node was not in the selected path.

beanz and others added 3 commits July 10, 2026 08:42
Environment variables with matching names on two commands with the
same parent were validated against the requirements of both commands.

It is caused by `Reset()` and `Validate()` walking the entire tree
rather than only the nodes on the selected path.
The fix hand-rolled a tree recursion and a *Node-keyed "selected"
set to scope Reset to the traced path. Since Visit already
surfaces every flag/positional/argument as a *Value, keep Reset on
the existing Visit walk and key tolerance off a *Value set
instead, dropping the bespoke recursion.

Promote the nodeValues helper to a Node.Values() method alongside
AllFlags/Leaves, reused by both Reset and Validate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alecthomas

Copy link
Copy Markdown
Owner

Thanks for tracking this down, @hindessm — the diagnosis is spot on and the regression tests are exactly what this needed. Env vars and defaults for commands that aren't on the selected path should never fail the parse.

I pushed a small follow-up commit (23f3f14) that keeps the same behaviour but reuses the existing machinery rather than introducing a parallel one:

  • Reset() stays on Visit() instead of a hand-rolled tree recursion. Since Visit already surfaces every flag/positional/argument as a *Value, we can key the "is this on the selected path?" tolerance off a map[*Value]bool rather than a *Node-keyed set. That drops the bespoke recursion and the extra selectedNodes helper.
  • nodeValues becomes a Node.Values() method, sitting alongside AllFlags/Leaves, and is reused by both Reset() and Validate().

Net effect is a little less code and one traversal idiom instead of two. Validate()'s c.Path walk is left as you had it — that's a genuinely different scope from Reset()'s whole-tree walk, so keeping them distinct is correct.

Tests and lint pass. Happy to squash or drop the commit if you'd rather keep authorship clean — whatever you prefer.

@alecthomas alecthomas merged commit c2c0229 into alecthomas:master Jul 11, 2026
5 checks passed
@hindessm

Copy link
Copy Markdown
Contributor Author

You're very welcome. I tripped over the bug and, having used kong for several projects, it was interesting trying to figure out how it fix it.

I'm happy with commit history as it is; thanks for cleaning it up and taking the time to provide the rationale.

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.

3 participants