From 916195bcf28e6f1fc0f05f8fdb9ff41a2563103f Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Tue, 10 Mar 2026 01:12:05 -0700 Subject: [PATCH] fix(vite): handle deleted files gracefully during HMR compilation When a file that Tailwind is watching (e.g. an SVG asset) gets deleted during HMR, the compile step fails with ENOENT because it tries to read a file that no longer exists. This wraps the compile call with a try-catch that specifically handles ENOENT errors by invalidating the compiler/scanner state and returning false, allowing the next rebuild cycle to proceed without the deleted file. Fixes #17532 Co-Authored-By: Claude Opus 4.6 --- packages/@tailwindcss-vite/src/index.ts | 35 +++++++++++++++++-------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index 3ab7c3a0f2f8..3ba0454a22a6 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -411,18 +411,31 @@ class Root { DEBUG && I.start('Setup compiler') let addBuildDependenciesPromises: Promise[] = [] - this.compiler = await compile(content, { - from: this.enableSourceMaps ? this.id : undefined, - base: inputBase, - shouldRewriteUrls: true, - onDependency: (path) => { - addWatchFile(path) - addBuildDependenciesPromises.push(this.addBuildDependency(path)) - }, + try { + this.compiler = await compile(content, { + from: this.enableSourceMaps ? this.id : undefined, + base: inputBase, + shouldRewriteUrls: true, + onDependency: (path) => { + addWatchFile(path) + addBuildDependenciesPromises.push(this.addBuildDependency(path)) + }, - customCssResolver: this.customCssResolver, - customJsResolver: this.customJsResolver, - }) + customCssResolver: this.customCssResolver, + customJsResolver: this.customJsResolver, + }) + } catch (error) { + // If a dependency file was deleted during HMR (e.g. an SVG asset), + // the compile step will fail with ENOENT. Handle this gracefully by + // invalidating the compiler so the next rebuild picks up the change. + if (error instanceof Error && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT') { + DEBUG && I.end('Setup compiler') + this.compiler = undefined + this.scanner = undefined + return false + } + throw error + } await Promise.all(addBuildDependenciesPromises) DEBUG && I.end('Setup compiler')