[fix] Add Windows stability check to file watcher to reduce false positives#14174
[fix] Add Windows stability check to file watcher to reduce false positives#14174lukasmasuch merged 4 commits intodevelopfrom
Conversation
On Windows, background processes (Windows Defender, Search Indexer, OneDrive) can trigger spurious file change events through the ReadDirectoryChangesW API used by watchdog. This causes false "File change" notifications even when no actual modifications were made. This adds a Windows-specific stability check: - After detecting an MD5 change, wait 50ms on Windows - Re-read the file's MD5 to verify the change is real - If MD5 reverts to original, treat as spurious event and ignore - If MD5 stays changed, proceed with normal change notification The fix only affects Windows (no latency impact on macOS/Linux) and only runs when an MD5 difference is detected (not on every event). Fixes #13954
✅ PR preview is ready!
|
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Consolidated Code ReviewSummaryThis PR adds a Windows-specific stability check to the event-based file watcher ( Files changed:
Code QualityBoth reviewers agreed the implementation is clean, well-scoped, and correctly positioned in the existing event handling flow. The stability check runs only after the mtime check and initial MD5 check have been exhausted, minimizing unnecessary work. Agreed minor issues:
Test CoverageBoth reviewers agreed the three new tests provide good coverage:
The mocking strategy is correct — Agreed residual gap: No real Windows integration/e2e validation exists for watchdog behavior. Both reviewers noted this but agreed it is outside the scope of this PR. Minor gap (opus-4.6-thinking): Tests could additionally verify that the stored Backwards CompatibilityBoth reviewers agreed: no backwards compatibility concerns. The change is additive and Windows-only. No public API, protobuf, or configuration changes. macOS/Linux behavior is completely unchanged. Security & RiskBoth reviewers assessed this as low risk. Agreed risk factors:
AccessibilityNot applicable — entirely backend/server-side with no frontend or UI changes. Reviewer AgreementBoth reviewers (
No areas of disagreement were identified between the two reviews. The opus-4.6-thinking review provided more granular analysis (e.g., the magic number constant suggestion, the Recommendations
VerdictAPPROVED: Both reviewers unanimously approve. The fix is well-scoped, addresses a real Windows-specific issue (linked to #13954), has clear and adequate test coverage, and poses no risk to other platforms. All noted issues are minor style suggestions and non-blocking. Consolidated review by 📋 Review by `gpt-5.3-codex-high`SummaryThis PR adds a Windows-only stability recheck in the event-based file watcher to reduce false positive change notifications caused by transient Code QualityThe implementation in Test CoverageUnit coverage is good for the new behavior:
These tests in Backwards CompatibilityNo public API or config changes are introduced. Behavior changes are intentionally limited to Windows and only after an MD5 mismatch is detected, so macOS/Linux behavior remains unchanged. Security & RiskNo direct security concerns identified. AccessibilityNo frontend/UI changes in this PR, so accessibility impact is not applicable. Recommendations
VerdictAPPROVED: The fix is well-scoped, adequately unit-tested for the intended logic, and appears safe to merge with only minor residual platform-validation risk. This is an automated AI review by 📋 Review by `opus-4.6-thinking`SummaryThis PR adds a Windows-specific stability check to the event-based file watcher to reduce false-positive "file changed" notifications. On Windows, background processes (Windows Defender, Search Indexer, OneDrive) can trigger spurious filesystem events via the Files changed:
Code QualityThe implementation is clean, well-scoped, and correctly placed in the existing event handling flow. The stability check runs only after all faster rejection paths (mtime check, initial MD5 check) have been exhausted, minimizing unnecessary work. A few minor observations:
Test CoverageThe three new tests provide good coverage of the stability check:
The mocking strategy is correct:
Existing tests are unaffected because Minor gap: The tests could additionally verify that the stored Backwards CompatibilityNo backwards compatibility concerns. The change is additive and only affects Windows:
Security & RiskLow risk. The main risks are:
AccessibilityNot applicable — this change is entirely backend/server-side with no frontend or UI changes. Recommendations
These are all minor suggestions and none are blocking. VerdictAPPROVED: A well-scoped, low-risk fix that addresses a real Windows-specific issue with clear test coverage and no impact on other platforms. The minor style suggestions above are non-blocking. This is an automated AI review by |
There was a problem hiding this comment.
Pull request overview
Adds a Windows-only “stability” verification step to the event-based file watcher to reduce false-positive change notifications caused by spurious filesystem events on Windows.
Changes:
- After an MD5 mismatch on Windows, sleep briefly and re-hash to confirm the change is stable before notifying.
- Expands module documentation with Windows-specific rationale and behavior.
- Adds unit tests covering transient vs real Windows changes and the non-Windows behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
lib/streamlit/watcher/event_based_path_watcher.py |
Implements the Windows stability re-check and documents the Windows-specific motivation. |
lib/tests/streamlit/watcher/event_based_path_watcher_test.py |
Adds unit tests validating Windows stability filtering and ensuring non-Windows behavior is unchanged. |
- Add blank line before bullet list for proper reST formatting - Add try/except for verification MD5 to prevent dropping real changes - Extract stability delay to _WINDOWS_STABILITY_DELAY_SECS constant
There was a problem hiding this comment.
Summary
This PR adds a Windows-specific stability check to the event-based file watcher (EventBasedPathWatcher) to reduce false-positive "file changed" notifications caused by background processes (Windows Defender, Search Indexer, OneDrive). When an MD5 content change is detected on Windows, the watcher waits 50ms and re-reads the file hash. If the hash reverts to the original value, the event is treated as spurious and suppressed. No behavioral changes on macOS/Linux.
Changes span two files:
lib/streamlit/watcher/event_based_path_watcher.py— stability check logic + docstring updatelib/tests/streamlit/watcher/event_based_path_watcher_test.py— three new unit tests
All three reviewers (claude-4.6-opus-high-thinking, gemini-3.1-pro, gpt-5.3-codex-high) unanimously approved the PR.
Code Quality
The implementation is clean, well-scoped, and follows existing patterns in the file watcher module. All reviewers agreed on the high quality of the code:
- The stability check is correctly positioned in the event handling pipeline — after the initial MD5 change is detected but before the callback fires.
- Error handling is appropriate: if the verification MD5 calculation fails (
StreamlitMaxRetriesError), the code gracefully falls back to using the initially computed MD5 rather than dropping the event. - The
_WINDOWS_STABILITY_DELAY_SECSconstant is properly typed asFinaland prefixed with_. - Logging uses the existing
_LOGGERat appropriate debug levels. - The
new_md5 = verification_md5update on line 548 correctly tracks the most recent known file state.
One reviewer (claude-4.6-opus-high-thinking) noted that time.sleep(0.05) blocks the watchdog observer's event dispatch thread, which could compound during bulk file operations (e.g., git checkout switching many files). For typical use cases this is negligible; this is a minor behavioral consideration, not a blocker.
Test Coverage
Three unit tests are added covering the primary scenarios — all reviewers agreed these are adequate:
- Transient change filtered — MD5 changes then reverts → callback suppressed
- Real change detected — MD5 changes and stays changed → callback fires
- Non-Windows bypass — stability check skipped entirely on Linux/macOS
Tests properly verify side effects (time.sleep called with correct delay, calc_md5 call counts, callback invocation).
Gap (raised by claude-4.6-opus-high-thinking, not mentioned by the other two reviewers): The StreamlitMaxRetriesError exception path in the verification step (lines 529–538) is not covered by any test. This is the path where the re-verification MD5 calculation fails and the code falls back to using the initially computed new_md5. A test for this path would improve confidence in the graceful degradation behavior. This is a nice-to-have rather than a blocker.
Backwards Compatibility
No breaking changes. All reviewers concur:
- The stability check is gated behind
env_util.IS_WINDOWS— no impact on macOS/Linux. - Only triggered after an MD5 difference is detected — no latency on events where content hasn't changed.
- The 50ms delay is minimal and only affects the watchdog observer thread on Windows.
- No public API or protocol changes.
Security & Risk
No security concerns identified. All reviewers agree. The changes are purely internal to the file watcher's event handling logic and do not affect WebSocket handling, authentication, session management, file serving, CORS, CSP, or any other security-sensitive surface.
Regression risk is low — the change is narrowly scoped to Windows file change event handling and has a safe fallback (proceed with the change) on any error.
External test recommendation
- Recommend external_test: No
- Triggered categories: None
- Key evidence:
lib/streamlit/watcher/event_based_path_watcher.py: Changes are confined to the internal file watcher event handler. No routing, auth, embedding, asset serving, WebSocket, CORS, CSP, storage, or SiS runtime changes.lib/tests/streamlit/watcher/event_based_path_watcher_test.py: Test-only changes.
- Suggested external test focus areas: None
- Confidence: High (all three reviewers independently reached the same conclusion)
- Assumptions and gaps: None
Accessibility
No frontend changes — not applicable. All reviewers agree.
Recommendations
-
Add a test for the
StreamlitMaxRetriesErrorfallback path in the stability check (lines 529–538). This would verify that when the verification MD5 calculation fails, the callback still fires with the initialnew_md5value. (Raised by 1 of 3 reviewers; nice-to-have.) -
Update the function-level import comment (line 513) to remove the "circular imports" justification, since
env_utilis a leaf module with only stdlib imports. The "rarely executed" rationale is sufficient. (Cosmetic.)
Verdict
APPROVED: Well-scoped, low-risk Windows bugfix with appropriate error handling and good test coverage. All three AI reviewers unanimously approved. The only notable gap is a missing test for the StreamlitMaxRetriesError fallback path, which is a nice-to-have rather than a blocker.
This is a consolidated AI review by claude-4.6-opus-high-thinking, synthesizing reviews from claude-4.6-opus-high-thinking, gemini-3.1-pro, and gpt-5.3-codex-high.
This review also includes 2 inline comment(s) on specific code lines.
Describe your changes
Fixes #13954
On Windows, background processes (Windows Defender, Search Indexer, OneDrive) can trigger spurious file change events through the
ReadDirectoryChangesWAPI used by the watchdog library. This can cause false "File change" notifications in Streamlit even when no actual modifications have been made.This PR adds a Windows-specific stability check to the event-based file watcher:
The fix only affects Windows (no latency impact on macOS/Linux) and only runs when an MD5 difference is detected (not on every event).
Testing Plan
test_windows_stability_check_filters_transient_changes- verifies transient changes are ignoredtest_windows_stability_check_allows_real_changes- verifies real changes are still detectedtest_non_windows_skips_stability_check- verifies no impact on non-Windows platforms