Skip to content

fix(StateManagerDisk): log error when corrupted state file is encountered - #7323

Open
dajiaohuang wants to merge 10 commits into
reflex-dev:mainfrom
dajiaohuang:main
Open

dajiaohuang wants to merge 10 commits into
reflex-dev:mainfrom
dajiaohuang:main

Conversation

@dajiaohuang

@dajiaohuang dajiaohuang commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Disk state loading now warns with the hashed filename and exception type/message when unexpected deserialization fails, then retains the existing default-state fallback. Expected StateSchemaMismatchError during hot reload returns None silently, matching Redis recovery.

The review revisions remove unrelated client-ID refactors, share warning-record filtering, use repr formatting for the exception message, and remove whitespace collapsing, message truncation and the added punctuation. Token redaction remains intentionally scoped: deserializers may include the session identifier in an exception message, as the regression test demonstrates. Formatting alone is not a redaction boundary.

Validation

  • Python 3.13.8 on Windows: disk manager unit tests 10 passed. The new schema-mismatch regression failed before the fix and passes afterward.
  • ruff check . passed; affected Python files pass ruff format and pyright.
  • Full unit suite with coverage: 9804 passed, 241 failed, 30 skipped. Failures include Windows symlink privilege errors and unmodified reflex_cli/v2 tests; this is not a passing full-suite result.
  • Full pyright reflex tests: one error in unmodified tests/units/docgen/test_class_and_component.py:397 (dataclasses.field doc argument with Python 3.13).
  • pre-commit --all-files: ruff format/check and codespell passed; update-pyi-files failed on generated select.pyi UTF-8 decoding and changed the hash file. The unrelated tracked hash change was reverted; later hooks did not run.
  • git diff --check passed. Current-head upstream CI and renewed maintainer review remain pending.

Scope

The state fallback behavior is unchanged. News fragment updated; no public component API or dependency changes.

…ered

Previously, a corrupted pickle file on disk would silently return None,
treating it the same as a missing file. Now an error is logged with
the token and path information before returning None, making corruption
observable without breaking the recovery behavior of returning default state.
@dajiaohuang
dajiaohuang requested a review from a team as a code owner September 25, 2026 03:57
@greptile-apps

greptile-apps Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with a non-blocking gap in warnings for corrupted BaseState files.

Findings

  1. P2 Corrupted sessions stay silent ▶

Summary

Adds a warning for unexpected disk-state load failures while keeping the existing fresh-state fallback.

  • Unexpected disk state load errors now produce a warning.

Reviews (7) · Last reviewed commit: "Merge remote-tracking branch 'upstream-g..." · Reviewed by Greptile

Comment thread reflex/istate/manager/disk.py Outdated
Comment thread reflex/istate/manager/disk.py Outdated
Comment thread tests/units/istate/manager/test_disk.py Outdated
Comment thread tests/units/istate/manager/test_disk.py

@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.

All reported issues were addressed across 3 files

Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.

Re-trigger cubic

Comment thread reflex/istate/manager/disk.py Outdated
Comment thread reflex/istate/manager/disk.py Outdated
Comment thread news/+disk-state-corruption.bugfix.md Outdated
Comment thread tests/units/istate/manager/test_disk.py Outdated
Comment thread reflex/istate/manager/disk.py Outdated

dajiaohuang commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor Author

The follow-up at f83a09f updates the message to describe the fallback accurately, identifies the failing file without logging the raw state token, scopes the regression assertions to this logger, and adds the PR-numbered news fragment. The second follow-up at 01a9f0f preserves normalized exception details while redacting both the full token and its identifier; a regression test checks that missing-module diagnostics remain useful without logging the token.

Final focused disk tests: 9 passed. Repository Ruff and format checks, targeted Pyright, and git diff --check pass. Whole-tree Pyright previously reported one unrelated overload error in tests/units/docgen/test_class_and_component.py:397. The full unit suite completed with 10,024 passed, 30 skipped, and 17 failures, all due to unavailable Windows symlink privileges (WinError 1314).

Current post-push snapshot at 01a9f0f: no commit statuses; 10 PR workflow runs are pending, queued, or in progress.

@codspeed

codspeed Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ 15 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 148 untouched benchmarks


Comparing dajiaohuang:main (19eb774) with main (7ccaa4e)

Open in CodSpeed

@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.

All reported issues were addressed across 2 files (changes from recent commits).

You’re at about 90% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread reflex/istate/manager/disk.py Outdated
Comment thread reflex/istate/manager/disk.py Outdated
Comment thread reflex/istate/manager/disk.py
Comment thread reflex/istate/manager/disk.py Outdated
Comment thread reflex/istate/manager/disk.py Outdated
Comment thread reflex/istate/manager/disk.py Outdated
Comment thread tests/units/istate/manager/test_disk.py Outdated
Comment thread tests/units/istate/manager/test_disk.py Outdated

@FarhanAliRaza FarhanAliRaza 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.

I tested this PR in a small app with state_manager_mode="disk". The app has a counter state and a notes state. I drove it in a browser and triggered backend hot reloads by editing the app file.

On main, a corrupt state file resets the state and logs nothing. On this PR, the same corrupt file logs one error per state file, and the page loads with default state. A plain restart keeps the state and logs nothing. A missing file logs nothing. The unit tests in test_disk.py pass.

I also added a field to a state class and reloaded. That path now logs an ERROR for a normal schema change.

Requested changes are in the inline comments.

@dajiaohuang

Copy link
Copy Markdown
Contributor Author

The requested changes are in 41039a51a39389f2eaca6fb50d81ca449a5cf040: schema mismatches return silently, unexpected load failures use logger.warning with %r, the redaction/normalization/cap and their extra tests are removed, unrelated existing-test literals are preserved, and the new tests share the log-filter helper. All six review threads are resolved.

The focused disk tests pass (9/9). Current-head hosted checks now report 145 successful and 3 skipped checks, with no failed or pending checks. This includes the unit, integration, application-harness, package-build and performance gates. Ready for another review; the hosted checks do not substitute for your browser hot-reload reproduction.

# Conflicts:
#	tests/units/istate/manager/test_disk.py
Comment on lines +162 to +163
except StateSchemaMismatchError:
return 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.

P2 Corrupted sessions stay silent

Corrupted BaseState files still produce no warning. BaseStateToken.deserialize calls BaseState._deserialize, which wraps every unpickling failure—including invalid or truncated data—in StateSchemaMismatchError. This handler silently returns None, so normal Reflex sessions fall back to fresh state without explaining why their saved values disappeared.

Distinguish actual schema changes from failed unpickling, and test corruption through BaseStateToken.

This branch has not been deployed

No deployments
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.

2 participants