jackwener/OpenCLI · warning
Failed to list trace artifacts in ${tracesDir}: ${err instan
Error message
Failed to list trace artifacts in ${tracesDir}: ${err instanceof Error ? err.message : String(err)} What it means
readTraceEntries lists the traces directory with fs.readdirSync to build retention entries. Any listing error other than ENOENT (missing dir is treated as "no traces") triggers this warning and returns an empty list. The library throws it so callers still get a safe empty result instead of crashing retention.
Source
Thrown at src/observation/retention.ts:151
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[] {
let names: string[];
try {
names = fs.readdirSync(tracesDir);
} catch (err) {
if (isEnoent(err)) return [];
warn(`Failed to list trace artifacts in ${tracesDir}: ${err instanceof Error ? err.message : String(err)}`);
return [];
}
const entries: TraceEntry[] = [];
for (const name of names) {
const dir = path.join(tracesDir, name);
try {
const stat = fs.statSync(dir);
if (!stat.isDirectory()) continue;
entries.push({
dir,
createdAtMs: readCreatedAtMs(dir, stat.mtimeMs),
sizeBytes: directorySize(dir),
protected: protectedDirs.has(path.resolve(dir)),
});
} catch (err) {
if (!isEnoent(err)) {
warn(`Failed to inspect trace artifact ${dir}: ${err instanceof Error ? err.message : String(err)}`);View on GitHub (pinned to 49907e53dc)
Solutions
- Verify tracesDir exists and is a directory (fs.statSync(tracesDir).isDirectory()); fix the configured path if not.
- Grant the process user read+execute permission on the traces directory.
- If the error is EMFILE/ENFILE, raise the file-descriptor limit (ulimit -n) or reduce concurrent I/O.
- Create the directory with mkdirSync(tracesDir, {recursive:true}) if you want an empty result to be legitimate.
Example fix
// before
warn(`Failed to list trace artifacts in ${tracesDir}: ...`);
// after
fs.mkdirSync(tracesDir, { recursive: true }); // ensure dir exists before listing
const stats = fs.statSync(tracesDir);
if (!stats.isDirectory()) throw new Error(`tracesDir is not a directory: ${tracesDir}`); Defensive patterns
Strategy: fallback
Validate before calling
let ok = true;
try { ok = fs.statSync(tracesDir).isDirectory(); } catch { ok = false; }
if (!ok) fs.mkdirSync(tracesDir, { recursive: true }); Type guard
function isReadableDir(p: string): boolean {
try {
const st = fs.statSync(p);
fs.accessSync(p, fs.constants.R_OK);
return st.isDirectory();
} catch { return false; }
} Try / catch
try {
names = fs.readdirSync(tracesDir);
} catch (err) {
if ((err as NodeJS.ErrnoException).code === 'ENOENT') { names = []; }
else { console.warn(`readdir failed: ${(err as Error).message}`); names = []; }
} Prevention
- Create the traces directory at startup with mkdirSync recursive.
- Point tracesDir at a directory, never a file path.
- Keep file-descriptor limits healthy (ulimit -n) under load.
- Verify permissions after container/user switches.
When it happens
Trigger: fs.readdirSync(tracesDir) throws for reasons other than the directory not existing: EACCES (no read permission), ENOTDIR (tracesDir path is a file), EIO (disk issue), or EMFILE/ENFILE (too many open files).
Common situations: tracesDir misconfigured to point at a regular file; permissions changed after a container/user switch; ulimit too low producing EMFILE under heavy load; networked filesystem briefly unavailable.
Related errors
- 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
- MiniMax music cannot reserve output file ${target}: ${error?
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/76bbd591444cf8d8.
Report an issue: GitHub.