Skip to content

fix: treat a file where a watched directory should be like a missing directory - #360

Merged
alexander-akait merged 1 commit into
mainfrom
fix/missing-under-file
Oct 17, 2026
Merged

alexander-akait merged 1 commit into
mainfrom
fix/missing-under-file

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Supersedes #226 (thanks @liximomo for the report and analysis).

With resolve.alias: { "@/foo": ["src/foo/index", "src/foo"] } and a file at src/foo, enhanced-resolve correctly reports src/foo/index, src/foo/index.js, … as missing dependencies: if src/foo later becomes a directory, webpack must re-resolve. watchpack then creates a DirectoryWatcher for src/foo, and its readdir fails with ENOTDIR:

  • onScanError logs Watchpack Error (initial scan): ENOTDIR: not a directory, scandir '…/src/foo' (on every poll with polling);
  • nothing watches for src/foo to become a directory, so src/foo/index.js appearing later is never reported (native watching).

#226 only hid the log line. This PR treats ENOTDIR on readdir like ENOENT: the directory is not there yet, so watchpack watches the parent and creates the watcher once a directory appears. This is the existing missing-directory path, including its retry for a path that is not a directory yet (#342).

Verified

  • Real webpack in watch mode with the alias above (native, Linux): main logs the ENOTDIR error, and this PR logs nothing. Both rebuild from file → error → directory. Here webpack also watches src/foo itself (the alias's second target), which hides the lost event.
  • watchpack alone, a missing foo/index.js while foo is a file, and then foo replaced by a directory with index.js:
main this PR
ENOTDIR error logged yes (repeated when polling) no
change for foo/index.js none (native) reported

Tests

  • test/MissingUnderFile.test.js covers the case above. It fails on main and passes here, with and without WATCHPACK_POLLING=200.
  • Full suite 209/209, and 205/205 with WATCHPACK_POLLING=200. npm run lint is clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_017TkBWTk3wcyUcJYDp5ZhaP


Generated by Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed file watching when a path’s parent initially exists as a file. After the parent is replaced with a directory, changes to the previously missing path are now detected without an initial-scan error.

@changeset-bot

changeset-bot Bot commented Oct 16, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3cc37aa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
watchpack Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codspeed

codspeed Bot commented Oct 16, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ 1 benchmark 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

✅ 36 untouched benchmarks


Comparing fix/missing-under-file (3cc37aa) with main (2ef4ad3)

Open in CodSpeed

@coderabbitai

coderabbitai Bot commented Oct 16, 2026

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 14b47a44-6a51-4451-b036-94c2d5cf4c57
📥 Commits

Reviewing files that changed from the base of the PR and between 2ef4ad3 and 3cc37aa.

📒 Files selected for processing: 3
  • .changeset/missing-under-file.md
  • lib/DirectoryWatcher.js
  • test/MissingUnderFile.test.js

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

Walkthrough

DirectoryWatcher.doScan now handles ENOTDIR from fs.readdir as a directory-removal condition. A regression test covers watching foo/index.js when foo initially exists as a file, then becomes a directory containing index.js. The test checks for a change event and no console errors. A patch changeset describes the scenario.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 3cc37

No actionable merge blocker is established for the reported missing-path behavior.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: treating a file at the expected watched-directory path like a missing directory.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.73%. Comparing base (2ef4ad3) to head (3cc37aa).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #360   +/-   ##
=======================================
  Coverage   92.72%   92.73%           
=======================================
  Files           8        8           
  Lines        1403     1404    +1     
  Branches      420      421    +1     
=======================================
+ Hits         1301     1302    +1     
  Misses         96       96           
  Partials        6        6           
Flag Coverage Δ
integration 92.73% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@alexander-akait
alexander-akait merged commit 022b223 into main Oct 17, 2026
51 checks passed
@alexander-akait
alexander-akait deleted the fix/missing-under-file branch October 17, 2026 10:26
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.

1 participant