From e0cdf6df134eaf8e7388083d76827d5052860770 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Thu, 9 Apr 2026 11:35:36 -0500 Subject: [PATCH] catch exception when directory contents change mid-traversal (#14342) --- news/changelog-1.10.md | 2 +- src/core/path.ts | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/news/changelog-1.10.md b/news/changelog-1.10.md index 2306b5ec79a..f3cadc2244c 100644 --- a/news/changelog-1.10.md +++ b/news/changelog-1.10.md @@ -40,4 +40,4 @@ All changes included in 1.10: - ([#6651](https://github.com/quarto-dev/quarto-cli/issues/6651)): Fix dart-sass compilation failing in enterprise environments where `.bat` files are blocked by group policy. - ([#14255](https://github.com/quarto-dev/quarto-cli/issues/14255)): Fix shortcodes inside inline and display math expressions not being resolved. - +- ([#14342](https://github.com/quarto-dev/quarto-cli/issues/14342)): Work around TOCTOU race in Deno's `expandGlobSync` that can cause unexpected exceptions to be raised while traversing directories during project initialization. \ No newline at end of file diff --git a/src/core/path.ts b/src/core/path.ts index 3d671af79ed..a2132b0fc90 100644 --- a/src/core/path.ts +++ b/src/core/path.ts @@ -172,13 +172,23 @@ export function resolvePathGlobs( const expandGlobs = (targetGlobs: string[]) => { const expanded: string[] = []; for (const glob of targetGlobs) { - for ( - const file of expandGlobSync( - glob, - { root, exclude, includeDirs: true, extended: true, globstar: true }, - ) - ) { - expanded.push(file.path); + try { + for ( + const file of expandGlobSync( + glob, + { root, exclude, includeDirs: true, extended: true, globstar: true }, + ) + ) { + expanded.push(file.path); + } + } catch (e) { + // expandGlobSync can throw NotFound if a file is deleted between + // directory listing and stat (TOCTOU race). This is expected during + // preview when the IDE or other processes modify the project + // directory concurrently. + if (!(e instanceof Deno.errors.NotFound)) { + throw e; + } } } return ld.uniq(expanded);