Skip to content

watch: an event on a path the OS cannot stat (name too long) kills the watch loop #897

Description

@tirth8205

Found while reviewing #893. Pre-existing on main, unrelated to that branch.

What happens

WatchBatchProcessor._relative_path (code_review_graph/incremental.py:2143) walks up to the nearest existing ancestor:

existing = candidate
while not existing.exists() and existing != lexical_root:
    existing = existing.parent

Path.exists() propagates OSError for a path the OS cannot even stat. A component longer than NAME_MAX is the easy case:

>>> Path('/tmp/' + 'a'*300 + '/x.py').exists()
OSError: [Errno 63] File name too long

That escapes _relative_path, is caught by process()'s except BaseException, sets self.failure, and raise_if_failed() ends the watch loop with RuntimeError: watch update failed. The watcher exits; under the daemon it is restarted (with backoff), pays for a full initial update, and dies again the next time the same event arrives.

Why it matters

Any tool that writes a too-long name inside a watched repo — a build cache, a generated fixture, a test that constructs deep paths — takes the watcher down. collect_all_files already guards for exactly this at incremental.py:1054-1060 ("Skip paths that would exceed OS filename limits"), so the concern is acknowledged elsewhere in the codebase; the watch path just doesn't have it.

Suggested fix

Guard the exists() walk (and the realpath/resolve calls near it) so an unstattable path is dropped like any other irrelevant event rather than killing the loop. Reuse the length check from collect_all_files if that reads better than catching OSError.

Reproduction

macOS, Python 3.13. Any watched repo; write a file whose name exceeds 255 bytes in a watched directory and the loop exits with watch update failed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions