New rule: Do you reject enum values your code does not define? - #13208
Open
bradystroud wants to merge 2 commits into
Open
New rule: Do you reject enum values your code does not define?#13208bradystroud wants to merge 2 commits into
bradystroud wants to merge 2 commits into
Conversation
Enum.TryParse returns true for any number the underlying type can hold, so an undefined value parses cleanly and falls through to the default member. The rule covers checking Enum.IsDefined, reserving an explicit Unknown member, logging the rejected value, using a mask for [Flags] enums, and validating at every entry point. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XLJSUhLVomcXxysdC8b7XQ
Contributor
🔍 Preview PR ChangesView updated pages in edit mode:
|
Contributor
|
Howzit @bradystroud, This PR has been here a while. Did you know you should avoid merge debt?
Thanks! |
tiagov8
reviewed
Aug 21, 2026
tiagov8
left a comment
Member
There was a problem hiding this comment.
Few suggestions for readability
| @@ -0,0 +1,88 @@ | |||
| --- | |||
| type: rule | |||
| title: Do you reject enum values your code does not define? | |||
Member
There was a problem hiding this comment.
Suggested change
| title: Do you reject enum values your code does not define? | |
| title: Do you reject undefined enum values? |
|
|
||
| `Enum.TryParse` tells you the text converted to the underlying integer type. It does not tell you the result is one of your members. A cast such as `(Status)99` does not throw either. Both produce a value that matches no `switch` branch and falls through to whatever your default is. | ||
|
|
||
| That default is where the damage happens. Enum members usually start at zero with the most ordinary state, so an unrecognized value quietly renders as the safest looking option. The screen shows a state that is wrong but plausible, and nobody questions it — until the record is picked up by a bulk action that should never have touched it. |
Member
There was a problem hiding this comment.
Suggested change
| That default is where the damage happens. Enum members usually start at zero with the most ordinary state, so an unrecognized value quietly renders as the safest looking option. The screen shows a state that is wrong but plausible, and nobody questions it — until the record is picked up by a bulk action that should never have touched it. | |
| That default is where the damage happens. Enum members usually start at zero with the most ordinary state, so an unrecognized value quietly renders as the safest looking option. The screen shows a state that is wrong but plausible, and nobody questions it, until the record is picked up by a bulk action that should never have touched it. |
|
|
||
| An unrecognized value usually means an upstream system added a member and did not tell you. If you map it to `Unknown` in silence, you lose the only notice you will get that the contract has moved. Log the raw value and its source, so the gap becomes a work item instead of a mystery. | ||
|
|
||
| ## Flags enums need a mask |
Member
There was a problem hiding this comment.
Suggested change
| ## Flags enums need a mask | |
| ## `Flags` enums need a mask |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
✏️ A lesson learned on a client project, generalised. A status parser accepted any numeric value, because
Enum.TryParse("99")returnstruewith an undefined result. The unrecognised status silently rendered as an ordinary state, which also made the record eligible for a bulk action it should never have entered.✏️ Added a new rule: Do you reject enum values your code does not define?
public/uploads/rules/reject-undefined-enum-values/rule.mdxcategories/software-engineering/rules-to-better-code.mdx, beside the existing enum rulesIt covers:
Enum.TryParseand a plain cast both produce an undefined member that matches noswitchbranchUnknown = 0member so an unrecognised value never lands on a real state[Flags]enums need a bit mask, becauseEnum.IsDefinedrejects valid combinationsValidators run and passing: frontmatter, check-mdx, markdownlint, category-sync, and find-rules-missing-endintro.
✏️ Written with Claude Code.
🤖 Generated with Claude Code
https://claude.ai/code/session_01XLJSUhLVomcXxysdC8b7XQ