From 9d8003cf22571387f9a2b1f6995a6313ac357c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 9 Apr 2026 12:22:36 +0200 Subject: [PATCH 1/2] fix: ignore temp files in Vite watcher to prevent dev server crash (#3585) On Linux, short-lived files (.tmp, .timestamp-*, editor swap files) can trigger a watchFs race condition in Deno where the watcher tries to open a file that was already deleted, crashing the dev server with ENOENT. Adding these patterns to the default watcher ignore list prevents the crash. Closes #3585 Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/plugin-vite/src/mod.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/packages/plugin-vite/src/mod.ts b/packages/plugin-vite/src/mod.ts index cd411cacfdc..c49c244526c 100644 --- a/packages/plugin-vite/src/mod.ts +++ b/packages/plugin-vite/src/mod.ts @@ -91,6 +91,23 @@ export function fresh(config?: FreshViteConfig): Plugin[] { isDev = env.command === "serve"; return { + server: { + watch: { + // Ignore temp files, editor swap files, and Vite timestamp + // files. On Linux, these short-lived files can trigger a + // watchFs race condition in Deno where the watcher tries to + // open a file that has already been deleted, crashing the + // dev server with ENOENT. + ignored: [ + "**/*.tmp.*", + "**/*.timestamp-*", + "**/*~", + "**/.#*", + "**/*.swp", + "**/*.swo", + ], + }, + }, esbuild: { jsx: "automatic", jsxImportSource: "preact", From ac6fcd39139841f01b2153ee0a80f1778c3dedc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 9 Apr 2026 13:06:32 +0200 Subject: [PATCH 2/2] test: verify server.watch.ignored patterns in Fresh Vite plugin Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/plugin-vite/tests/config_test.ts | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 packages/plugin-vite/tests/config_test.ts diff --git a/packages/plugin-vite/tests/config_test.ts b/packages/plugin-vite/tests/config_test.ts new file mode 100644 index 00000000000..cd650105de8 --- /dev/null +++ b/packages/plugin-vite/tests/config_test.ts @@ -0,0 +1,26 @@ +import { expect } from "@std/expect"; +import { fresh } from "../src/mod.ts"; +import type { Plugin } from "vite"; + +Deno.test("fresh plugin - sets server.watch.ignored patterns", () => { + const plugins = fresh() as Plugin[]; + const freshPlugin = plugins.find((p) => p.name === "fresh"); + expect(freshPlugin).toBeDefined(); + + // Call the config hook as Vite would during dev + // deno-lint-ignore no-explicit-any + const configFn = freshPlugin!.config as any; + const result = configFn({}, { command: "serve" }); + + const ignored = result?.server?.watch?.ignored; + expect(ignored).toBeDefined(); + expect(Array.isArray(ignored)).toBe(true); + + // Should ignore temp files, editor swap files, and Vite timestamp files + expect(ignored).toContain("**/*.tmp.*"); + expect(ignored).toContain("**/*.timestamp-*"); + expect(ignored).toContain("**/*.swp"); + expect(ignored).toContain("**/*.swo"); + expect(ignored).toContain("**/*~"); + expect(ignored).toContain("**/.#*"); +});