tailwindcss: Transient read failure may cause permanent failure to watch file
V3.1.18 Tailwind CLI, Visual Studio 2022 as editor. Node v14.18.1 Chrome Window 10 (No Docker or WSL)
This issue is a very close relative of #7759, but I think it might be quite specialised so I don’t want to pollute that one.
I have a rather odd web project, which has a single HTML file. So the content section of tailwind.config.js looks like this:
content: [
"./wwwroot/index.html"
],
I run a tailwind CLI watcher with a command like this:
npx tailwindcss --output wwwroot/css/tailwind.css --watch -i css/twbase.css
I am suffering from the problem described in #7759 where the watcher stops watching after a while - anywhere between almost immediately and after lots and lots of successful rebuilds.
By using the “Process Monitor” utility to observe the filesystem activity on the index.html file, I have observed that when Visual Studio (devenv.exe) is saving index.html, it goes through a rename/replace process which means there is a window of time in which the index.html file does not actually exist. It appears that node.exe (i.e. Tailwind) sometimes tries to read the file during this window and finds it to be missing.
This apparently causes Tailwind to stop watching that file.

The blue selected line in the image is Node getting a file-not-found failure doing a CreateFile (it’s actually an open-to-read) on index.html in the middle of devenv doing a rename dance. I think that’s a smoking gun.
If I change the content file specification to be a wildcard, then my first impression is that things are much more robust:
content: [
"./wwwroot/*.html"
],
So:
- Is it possible/likely that TW is converting a transient read-failure on a watched file into a permanent failure to watch that file?
- If so, could this be fixed?
Even without the specific Visual Studio rename thing, transient read failures are probably an inescapable feature of Windows, because it’s so common that people have tools like anti-virus and cloud-backup and indexers which do lots of automatic file opening.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 38 (20 by maintainers)
O_O YES 🎉 Gonna re-close this but let me know if you run into anything else. Seriously, thank you for all of your help. It’s very appreciated!
Yeah, you’re totally right. The unlink event won’t fire for files that don’t match the glob. However, unconditionally adding files back from an unlink is unnecessary so I’ve optimized that by only doing it for “static” globs. And I’ve also filtered out the rename events that don’t match the defined content paths.
@willdean can you give the insiders build a check (it’ll take a few minutes to publish)? Hopefully this will work… 🤞
Hi @thecrypticace - Looks like that’s working, many thanks.
In testing this I have noticed an unrelated ‘feature’ where TW does not remove selectors that are no longer needed until the CLI is restarted (i.e. regenerations of the file are not as ‘clean’ as the first generation). Is this intended? If not I’ll file a separate issue with explicit repro steps.
Unfortunately your fix doesn’t work for me - I added it (with some logging), and I get an unlink event for every save, but nothing else.
I have some other lines of enquiry, because my little tester is showing a different series of events to those that I get in TW when I remove all of TW’s event handlers and just log Chokidar events. This may be something about Chokidar configuration.
So it appears that this fixes it for the CLI:
The rename operation firing an
unlinkcauses it to be removed from the list of watched files.Yeah I just poked around and chokidar is not firing
changeevents when saved by Visual Studio. It is however firing a “raw” event with details which I can see:It should be firing a change event but I’m not sure why it’s not. I’d imagine this is a chokidar bug but maybe we can do something to work around it. I’ll keep poking around.