From f36186ba141d19a0ec1ef0819ccd9a20f9232f3e Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Wed, 28 Aug 2024 11:56:22 +0200 Subject: [PATCH 1/2] windows - wait to file to unlock for removal while removing dir or file, it happens that EBUSY error could happen with file being used and lock. This is a simple way to wait for file to be unlocked, with a fail safe of max try to avoid infinite loop. --- src/deno_ral/fs.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/deno_ral/fs.ts b/src/deno_ral/fs.ts index e48e1c68ca9..644a95f0a13 100644 --- a/src/deno_ral/fs.ts +++ b/src/deno_ral/fs.ts @@ -8,6 +8,7 @@ import { fromFileUrl } from "./path.ts"; import { resolve, SEP as SEPARATOR } from "./path.ts"; import { copySync } from "fs/copy"; import { existsSync } from "fs/exists"; +import { isWindows } from "./platform.ts"; export { ensureDir, ensureDirSync } from "fs/ensure-dir"; export { existsSync } from "fs/exists"; @@ -116,8 +117,25 @@ export function safeRemoveSync( try { Deno.removeSync(file, options); } catch (e) { + let lastError = e; + // WINDOWS ONLY: Retry on windows to let time to file to unlock + if (isWindows && e.code === "EBUSY") { + let nTry: number = 1; + // high number to prevent infinite loop + const maxTry: number = 500; + let eCode = e.code; + while (eCode === "EBUSY" && nTry <= maxTry) { + try { + Deno.removeSync(file, options); + } catch (e) { + lastError = e; + eCode = e.code; + nTry++; + } + } + } if (existsSync(file)) { - throw e; + throw lastError; } } } From 14eaafacfff5452b0870fdace6f5c5e198ddf81a Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Wed, 3 Dec 2025 11:55:40 +0100 Subject: [PATCH 2/2] Fix TypeScript type errors in error handling Add type guard for error code checking to properly handle unknown error types in catch blocks. --- src/deno_ral/fs.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/deno_ral/fs.ts b/src/deno_ral/fs.ts index 644a95f0a13..0b28375ceb3 100644 --- a/src/deno_ral/fs.ts +++ b/src/deno_ral/fs.ts @@ -22,6 +22,15 @@ export { moveSync } from "fs/move"; export { emptyDirSync } from "fs/empty-dir"; export type { WalkEntry } from "fs/walk"; +// Error type guard for file system operations +interface ErrorWithCode { + code: string; +} + +function hasErrorCode(e: unknown): e is ErrorWithCode { + return typeof e === "object" && e !== null && "code" in e; +} + // It looks like these exports disappeared when Deno moved to JSR? :( // from https://jsr.io/@std/fs/1.0.3/_get_file_info_type.ts @@ -119,7 +128,7 @@ export function safeRemoveSync( } catch (e) { let lastError = e; // WINDOWS ONLY: Retry on windows to let time to file to unlock - if (isWindows && e.code === "EBUSY") { + if (isWindows && hasErrorCode(e) && e.code === "EBUSY") { let nTry: number = 1; // high number to prevent infinite loop const maxTry: number = 500; @@ -127,9 +136,10 @@ export function safeRemoveSync( while (eCode === "EBUSY" && nTry <= maxTry) { try { Deno.removeSync(file, options); - } catch (e) { - lastError = e; - eCode = e.code; + break; // Success, exit the loop + } catch (err) { + lastError = err; + eCode = hasErrorCode(err) ? err.code : ""; nTry++; } }