Skip to content

Validate reserved state names before registration - #7136

Draft
FarhanAliRaza wants to merge 1 commit into
reflex-dev:mainfrom
FarhanAliRaza:fix-reserved-state-names
Draft

FarhanAliRaza wants to merge 1 commit into
reflex-dev:mainfrom
FarhanAliRaza:fix-reserved-state-names

Conversation

@FarhanAliRaza

@FarhanAliRaza FarhanAliRaza commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

State vars named _get_was_touched or _update_was_touched can replace framework helpers and crash persistence or cleanup. Other collisions, including get_fields and dirty_vars, can break class creation or bookkeeping. This rejects reserved declarations before field collection and state initialization, and applies the same validation to dynamic vars, fields, event handlers, and route arguments.

Reserved names are derived once from BaseState and its framework bases. Ordinary vars, inherited user vars, Python protocols, and explicitly marked method overrides remain supported. Validation also checks state mixins, ordinary Python mixins, and inherited model fields without invoking descriptors.

This changes the default behavior. Existing apps can temporarily set REFLEX_STATE_ALLOW_RESERVED_NAMES=1 to retain legacy handling of conflicting vars with a deprecation warning until 1.0. The flag preserves the old behavior, including collision-related crashes; renaming conflicting declarations resolves them. Migration guidance and fragments for both affected packages are included.

Supersedes #7132 and the method-specific follow-up fix for #7135.

Closes #7091.
Closes #7135.

Validation:

  • All 35 new cases pass; on the unchanged base, the 33 regression cases fail and the two compatibility controls pass.

  • The final state suites pass all 312 tests.

  • Full unit suite: 8,626 passed, 18 skipped. The coverage gate exits nonzero at 71.34%, below the required 72%; the unchanged base also reports 71.34% with 8,591 passed and 18 skipped. The new validator has 97.59% coverage; state plus validation have 86.19%.

  • Full pyright reflex tests passes. All commit hooks pass, including Ruff, codespell, stub generation, Pyright, and ty.

  • Repository Ruff checks and formatting pass with the ignored ignore/ scratch tree excluded.

  • Followed CONTRIBUTING.md and added regression tests, migration documentation, and package news fragments.

  • Breaking change with a temporary compatibility opt-in.

  • Checked overlapping work: this is the centralized replacement for Call _get_was_touched through BaseState so a state var cannot shadow it #7132 and the narrow A backend var named _update_was_touched breaks state cleanup and persistence checks #7135 follow-up.

Review in cubic

@FarhanAliRaza
FarhanAliRaza requested review from a team and Alek99 as code owners September 14, 2026 11:47
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-14T11:52:51.895663Z f901a6b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 8 files

Re-trigger cubic

@greptile-apps

greptile-apps Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The PR is not safe to merge until the framework-owned router field is retained in the reserved namespace.

Findings

  1. P1 Router Remains Shadowable

Summary

  • Adds a cached framework namespace and validating state metaclass.
  • Applies validation to dynamic fields, variables, handlers, and route arguments.
  • Preserves explicitly marked framework method overrides.
  • Adds REFLEX_STATE_ALLOW_RESERVED_NAMES as a temporary migration escape hatch.
  • One framework-owned field, router, is mistakenly excluded from the reserved set and remains vulnerable to static shadowing.

Reviews (1) · Last reviewed commit: "Validate reserved state names before cla..."

Comment on lines +41 to +43
for name, field in BaseState.__fields__.items():
if field.is_var:
members.pop(name, None)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Router Remains Shadowable

_reserved_state_members() removes every field marked is_var, but BaseState.router is a framework-owned RouterData field with that flag. A subclass can therefore declare an ordinary router field without being rejected. Instances then initialize router with the user value, causing framework accesses such as self.router._page, self.router.session, or self.router.url to fail with an attribute or type error.

@codspeed-hq

codspeed-hq Bot commented Sep 14, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 40 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing FarhanAliRaza:fix-reserved-state-names (f901a6b) with main (cc2d9a4)

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@FarhanAliRaza
FarhanAliRaza marked this pull request as draft September 14, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant