change event is fired for directories and files that were created shortly before startTime, when startTime is set
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 400
- Forks
- 111
- Avg merge
- 11h 16m
- Merged PRs (30d)
- 5
Description
Have you used AI?
No
Bug Description
When Watchpack is initialized with startTime: Date.now(), it fires the change event for directories / files that were created shortly before.
When startTime is not set, the change event is not fired as desired (fixed with test coverage in #150).
README.md documents startTime as being an optional number, and "Watching can be started in the past. This way watching can start after file reading.". The observed behavior of getting unwanted events is surprising.
Moreover, the source shows that FS_ACCURACY (up to two seconds!) is added to the start time. Any file/directory older than this time will be flagged as changed. This is not documented and surprising (and contributing to this bug):
https://github.com/webpack/watchpack/blob/59adaaa473f0e164c7d88b8b8184b01693902d05/lib/DirectoryWatcher.js#L430
The above source also shows the use of birthtime/btime instead of ctime. This is surprising and not documented in README.
I tried using fs.utimes with a past date as a work-around. This works on macOS but failed on Linux and Windows, because fs.utimes updates mtime but not btime. The use of btime appears to be introduced in #183. The work-around works in watchpack@2.0.1 (which is before 2.1.0 that includes #183).
Link to Minimal Reproduction and step to reproduce
npm install watchpack ( tested with latest version watchpack@2.5.1 and Node 25.9.0)
Save following file as test.mjs and run node test.mjs:
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import Watchpack from "watchpack";
const base = path.join(os.tmpdir(), "watchpack_repro");
await fs.rm(base, { recursive: true }).catch(() => {}); // ignore ENOENT
await fs.mkdir(base);
await fs.mkdir(path.join(base, "subdir"));
const dateInPast = Date.now() / 1000 - 10; // 10 seconds older should be plenty
// await fs.utimes(path.join(base, 'subdir'), dateInPast, dateInPast);
// ^ Works on macOS (changes btime), not on Linux or Windows. Also works in watchpack<=2.0.1
const w = new Watchpack({});
w.on("change", console.log);
w.watch({
directories: [base],
missing: [],
startTime: Date.now(),
});
console.log("Waiting 2 seconds. Should not log anything.");
await new Promise(r => setTimeout(r, 2000));
w.close();
Expected Behavior
Should not log change events for files/directories that were created shortly before Watchpack is initialized.
Actual Behavior
Logs a change event for the subdirectory that was created immediately before:
/tmp/watchpack_repro/subdir 1777218474762 scan (dir)
(the minimal STR uses a directory, but this also reproduces for files)
Environment
Node: v25.9.0 (and also tested v20.20.2)
Linux: Ubuntu 24.04.4 LTS
macOS: 15.7.5
Is this a regression?
No
Last Working Version
No response
Additional Context
The fs.utimes work-around to get the test to pass works on macOS because it apparently changes the btime as well:
$ mkdir d;node -e 'require("fs/promises").utimes("d", 1234, 5678)';stat -x d
...
Access: Thu Jan 1 01:20:34 1970
Modify: Thu Jan 1 02:34:38 1970
Change: Sun Apr 26 18:19:50 2026
Birth: Thu Jan 1 02:34:38 1970
On Linux, the Birth time is not modified when I run the same command.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reproduction in test.mjs and inspect lib/DirectoryWatcher.js around line 430, where FS_ACCURACY and birthtime are used with startTime. Verify the behavior on the reported platforms and check the existing watcher tests, including the coverage referenced in #150. Done means recently created files and directories do not emit unwanted change events when startTime is set, with any relevant semantics documented in README.md.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100