Fix/autoreload watcher race#10226
Open
Felipenguim wants to merge 5 commits into
Open
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Sanjays2402
reviewed
Jul 19, 2026
| continue | ||
| pymtime = module_mtime.mtime | ||
|
|
||
| existing_mtime = self.watcher_modules_mtimes.get(modname) |
There was a problem hiding this comment.
This separate map never gets cleared when a module name is rebound to another __file__. check() explicitly drops modules_mtimes on that path but leaves this old baseline behind, so a replacement file with an older mtime and subsequent edits stay invisible until its timestamp passes the previous file’s.
Contributor
Author
for more information, see https://pre-commit.ci
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.
📝 Summary
Closes #10191
Related: #10225 (found while validating this fix)
The bug
marimo's module autoreload has two independent consumers sharing the same
ModuleReloaderstate (modules_mtimes/stale_modulesinmarimo/_runtime/reload/autoreload.py). Both callModuleReloader.check(), which one sees a file's mtime change first "consumes" it for both, creating a race conditioncell_scope()reloads the module correctly, but the watcher never gets to run its transitive dependency analysis for that change. like the self-import cycle in #10191 — never get marked stale.The fix
ModuleReloadergets a second, independent mtime baseline (watcher_modules_mtimes) and acheck_for_watcher()method, used only byModuleWatcher. This lets the watcher detect "did this file change since I last checked" on its own terms, regardless of whethercell_scope()already reloaded it in the meantime._check_modulesnow calls bothcheck()(kept —cell_uses_stale_modules/flag_if_imports_stalestill rely on it being populated) andcheck_for_watcher()(used for the transitive-dependency computation).Tests
test_reload_self_import_cycle: the scenario from the issue.test_reload_self_import_cycle_race_with_other_cell: same setup, but forces an unrelated cell to rerun right after the file changes and before the watcher's next poll. Specifically exercises the race.Note on #10225
While testing this manually against my own editable install, I ran into a separate, pre-existing bug:
modulefindercrashes on marimo's own namespace packages, which silently breaks dependency detection, but only in dev setup, not for regular users. It briefly made this fix look broken even though it wasn't, but when I tested it with the a built app, it worked.📋 Pre-Review Checklist
✅ Merge Checklist