Skip to content

Commit

Permalink
Avoid uncaught exception when file is deleted (#3313)
Browse files Browse the repository at this point in the history
If I run `snowpack dev` and then delete a watched file, the process crashes with this error:

  ⠸ watching for file changes...node:internal/process/promises:246
            triggerUncaughtException(err, true /* fromPromise */);
            ^
  [Error: ENOENT: no such file or directory, open '/home/ahupp/new-dir/src/index.js'] {
    errno: -2,
    code: 'ENOENT',
    syscall: 'open',
    path: '/home/ahupp/new-dir/src/index.js'
  }

The root issue seems to be that 'unlink' events go through the same
path as change/add events, which try to read the file and throw an
uncaught exception.  This diff moves the call to `prepareSingleFile`
so that it only runs in the change and add paths.

I'm not very familiar with this codebase so feel free to tell me this
is the wrong approach, but it does fix the problem for me.

This should fix #3252

Other issues to consider:

 * The stack trace for these exceptions seems to be lost, which makes
   debugging this more challenging than necessary.
 * Should exceptions from chokidar watch events be caught and logged?
  • Loading branch information
ahupp committed May 20, 2021
1 parent 19b236d commit 45e2a22
Showing 1 changed file with 12 additions and 8 deletions.
20 changes: 12 additions & 8 deletions snowpack/src/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -926,11 +926,11 @@ export async function startServer(

// Watch src files
async function onWatchEvent(fileLoc: string) {

logger.info(
colors.cyan('File changed: ') + path.relative(config.workspaceRoot || config.root, fileLoc),
);
// TODO: If this needs to build a new dependency, report to the browser via HMR event.
await pkgSource.prepareSingleFile(fileLoc);

const updatedUrls = getUrlsForFile(fileLoc, config);
if (updatedUrls) {
handleHmrUpdate && handleHmrUpdate(fileLoc, updatedUrls[0]);
Expand All @@ -940,6 +940,7 @@ export async function startServer(
inMemoryBuildCache.delete(getCacheKey(fileLoc, {isSSR: true, mode: config.mode}));
inMemoryBuildCache.delete(getCacheKey(fileLoc, {isSSR: false, mode: config.mode}));
await onFileChangeCallback({filePath: fileLoc});

for (const plugin of config.plugins) {
plugin.onChange && plugin.onChange({filePath: fileLoc});
}
Expand All @@ -956,18 +957,21 @@ export async function startServer(
disableGlobbing: false,
useFsEvents: isFsEventsEnabled(),
});
watcher.on('add', (fileLoc) => {
watcher.on('add', async (fileLoc) => {
knownETags.clear();
onWatchEvent(fileLoc);
await pkgSource.prepareSingleFile(fileLoc);
await onWatchEvent(fileLoc);
fileToUrlMapping.add(fileLoc, getUrlsForFile(fileLoc, config)!);
});
watcher.on('unlink', (fileLoc) => {
watcher.on('unlink', async (fileLoc) => {
knownETags.clear();
onWatchEvent(fileLoc);
await onWatchEvent(fileLoc);
fileToUrlMapping.delete(fileLoc);
});
watcher.on('change', (fileLoc) => {
onWatchEvent(fileLoc);
watcher.on('change', async (fileLoc) => {
// TODO: If this needs to build a new dependency, report to the browser via HMR event.
await pkgSource.prepareSingleFile(fileLoc);
await onWatchEvent(fileLoc);
});
// [hmrDelay] - Let users with noisy startups delay HMR (ex: 11ty, tsc builds)
setTimeout(() => {
Expand Down

1 comment on commit 45e2a22

@vercel
Copy link

@vercel vercel bot commented on 45e2a22 May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.