vercel/turborepo · warning
Unable to remove temporary directory ${tempDir}:\n${formatEr
Error message
Unable to remove temporary directory ${tempDir}:\n${formatError(error)} What it means
After cloning/extracting an example, downloadAndExtractExample's cleanupCloneDirectory (packages/turbo-utils/src/examples.ts:524) tries to remove the temporary clone directory with rmSync (recursive, force, 5 retries, 100ms delay). If removal still throws, it only warns — the example creation itself has already succeeded; the temp directory is left behind.
Source
Thrown at packages/turbo-utils/src/examples.ts:530
function runGit(args: Array<string>, cwd?: string): void {
try {
execFileSync("git", args, { cwd, stdio: "pipe" });
} catch (error) {
throw new Error(`\`git ${args[0]}\` failed:\n${formatError(error)}`);
}
}
function cleanupCloneDirectory(tempDir: string): void {
try {
rmSync(tempDir, {
recursive: true,
force: true,
maxRetries: 5,
retryDelay: 100
});
} catch (error) {
warn(
`Unable to remove temporary directory ${tempDir}:\n${formatError(error)}`
);
}
}
export async function downloadAndExtractExample(root: string, name: string) {
// Validate example name to prevent path traversal and argument injection
// Only allow alphanumeric characters, hyphens, and underscores
if (!name || !/^[a-zA-Z0-9_-]+$/.test(name)) {
throw new Error(`Invalid example name: ${name}`);
}
// Normalize and validate the root directory to prevent unsafe git arguments
const normalizedRoot = resolve(root);
assertSafeGitArgument(normalizedRoot, "project root");
const tempDir = join(normalizedRoot, ".turbo-clone-temp");
assertSafeGitArgument(tempDir, "temporary directory");View on GitHub (pinned to f9245100cf)
Solutions
- Ignore the warning if the example was created correctly — only the temp copy is left behind.
- Remove the leftover directory manually once nothing holds locks: rm -rf <tempDir> (path is printed in the warning).
- On Windows, close editors/explorer windows and let antivirus finish scanning before retrying deletion.
- If it recurs in CI, pre-clean the temp root (set/point TMPDIR to a fresh directory) before running the create command.
Example fix
# before: warning about locked temp dir during `turbo create` Unable to remove temporary directory /tmp/xyz-clone: EBUSY ... # after: manually clean up afterwards (safe, example already extracted) rm -rf /tmp/xyz-clone
Defensive patterns
Strategy: try-catch
Try / catch
// cleanupCloneDirectory already swallows and warns; keep that shape for your own cleanup
import { rmSync } from "node:fs";
try {
rmSync(tempDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
} catch (error) {
console.warn(`Unable to remove temporary directory ${tempDir}:\n${formatError(error)}`);
// example extraction already succeeded — do not rethrow
} Prevention
- Point TMPDIR at a private, short-lived directory per CI job so leftovers are reaped by the runner anyway.
- On Windows, close handles and exclude build temp dirs from antivirus real-time scans.
- Treat this warning as informational; success of the create/example flow is not affected.
When it happens
Trigger: rmSync failing after 5 retries: files in the temp dir are locked by another process (Windows file locking), permission denied on some entries, or the directory is on a filesystem with delayed unlink semantics. Only reached when `turbo create`/example download used a temp clone directory.
Common situations: Windows with antivirus/indexer/Explorer holding handles inside the temp dir, CI containers with odd tmpfs permissions, or disk state where recursive unlink races with file creation. The warning is cosmetic: the downloaded example is already in place.
AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17).
Data as JSON: /api/errors/5bc7e807cbb469cb.
Report an issue: GitHub.