jackwener/OpenCLI · warning
Failed to prune trace artifact ${dir}: ${err instanceof Erro
Error message
Failed to prune trace artifact ${dir}: ${err instanceof Error ? err.message : String(err)} What it means
pruneTraceArtifacts deletes old trace artifact directories with fs.rmSync after deciding which entries exceed retention limits. When the OS refuses the recursive removal (permissions, files locked by another process, EPERM/EBUSY/EACCES), the error is caught per-directory and surfaced as this warning while other directories continue to be pruned. It is non-fatal: the affected dir simply stays on disk and is reported as kept.
Source
Thrown at src/observation/retention.ts:127
remaining = remaining.filter((entry) => entry.dir !== victim.dir);
}
let remainingBytes = remaining.reduce((sum, entry) => sum + entry.sizeBytes, 0);
while (remainingBytes > policy.maxBytesPerProfile) {
const victim = remaining.find((entry) => !entry.protected);
if (!victim) break;
deleted.add(victim.dir);
remaining = remaining.filter((entry) => entry.dir !== victim.dir);
remainingBytes -= victim.sizeBytes;
}
const deletedDirs: string[] = [];
for (const dir of sorted.map((entry) => entry.dir).filter((dir) => deleted.has(dir))) {
try {
fs.rmSync(dir, { recursive: true, force: true });
deletedDirs.push(dir);
} catch (err) {
warn(`Failed to prune trace artifact ${dir}: ${err instanceof Error ? err.message : String(err)}`);
}
}
const keptEntries = entries.filter((entry) => !deletedDirs.includes(entry.dir));
return {
scanned: entries.length,
deleted: deletedDirs,
kept: keptEntries.map((entry) => entry.dir),
totalBytesBefore,
totalBytesAfter: keptEntries.reduce((sum, entry) => sum + entry.sizeBytes, 0),
};
}
function readTraceEntries(
tracesDir: string,
protectedDirs: Set<string>,
warn: (message: string) => void,
): TraceEntry[] {View on GitHub (pinned to 49907e53dc)
Solutions
- Check permissions on the failing directory (ls -la) and chown/chmod so the process user can delete it.
- Close processes holding files open in the traces directory (or retry later — the next prune pass will retry).
- On Windows, exclude the traces directory from antivirus/sync tools that lock files.
- If a specific dir persistently fails, delete it manually and re-run the retention pass.
Example fix
// before
fs.rmSync(dir, { recursive: true, force: true });
// after
try {
fs.rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
} catch (err) {
fs.chmodSync(dir, 0o700);
fs.rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
} Defensive patterns
Strategy: try-catch
Validate before calling
const st = fs.statSync(dir);
if (st.isDirectory() && fs.accessSync(dir, fs.constants.W_OK)) throw new Error(`no write access: ${dir}`); Type guard
function isRemovable(dir: string): boolean {
try { fs.accessSync(dir, fs.constants.W_OK); return fs.statSync(dir).isDirectory(); } catch { return false; }
} Try / catch
try {
fs.rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
} catch (err) {
const code = (err as NodeJS.ErrnoException).code;
console.warn(`skip ${dir}: ${code ?? err}`); // EPERM/EBUSY -> retry later
} Prevention
- Close trace viewers/editors holding files open before running retention.
- Run retention as the same user that created the traces.
- Exclude the traces directory from antivirus/sync software.
- Use rmSync maxRetries/retryDelay for transient locks.
When it happens
Trigger: fs.rmSync(dir, {recursive:true, force:true}) throws for a specific trace directory — e.g. the directory contains read-only files, is held open by another process (a running trace viewer, editor, antivirus on Windows), or the current user lacks write permission on a parent.
Common situations: Running retention cleanup while a debugger or trace tool has files open; traces directory owned by a different user (CI artifacts written as root, pruned as non-root); Windows antivirus or OneDrive sync locking files; NFS/EBS stale handles.
Related errors
- Verify command returned no metric for baseline
- File could not be read: ${path}
- Receipt file cannot be read: ${receipt}
- Could not store Midjourney ${kind} at ${filePath}: ${errorMe
- Could not read Midjourney usage snapshots: ${errorMessage(er
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/d97f76a5c5d50d3a.
Report an issue: GitHub.