affaan-m/ECC · error · Error
Unsafe state-store path
Error message
Unsafe state-store path '${dbPath}': database path is not a regular file What it means
assertSafeDatabaseFile checks the database path before the store reads or writes it: it lstats the path (tolerating ENOENT, since first-run means the file does not exist yet), rejects symlinks, and rejects any existing entry that is not a regular file. The library throws this error because openDatabase/writeDatabaseFileAtomic/readDatabaseFile must only read and atomically replace an actual SQLite file — operating on a directory, FIFO, socket or device at dbPath would corrupt state or leak data. Note the file is allowed to not exist; it must merely be a regular file if it does exist.
Solutions
- Check the path: ls -la <dbPath>; if it is a directory, remove it (rm -rf or mv aside) so the library can create the regular SQLite file there
- Pass the full FILE path as dbPath — if you have a directory, append the filename: createStateStore({ dbPath: path.join(dir, 'state.db') }) or rely on the default ~/.claude/ecc/state.db
- If the path is a socket/FIFO from another process, stop that process or relocate the store with a different dbPath
- If a mount shadows the path, unmount or re-point the mount and retry
Example fix
// before: dbPath points at a directory that exists
createStateStore({ dbPath: '/var/lib/ecc' });
// after: point at a regular file inside that directory
import path from 'path';
createStateStore({ dbPath: path.join('/var/lib/ecc', 'state.db') }); Defensive patterns
Strategy: validation
Validate before calling
import fs from 'fs';
export function assertDbPathUsable(dbPath) {
const st = fs.lstatSync(dbPath, { throwIfNoEntry: false });
if (st && st.isSymbolicLink()) {
throw new Error(`dbPath '${dbPath}' is a symlink; refusing to use it`);
}
if (st && !st.isFile()) {
throw new Error(`dbPath '${dbPath}' exists but is not a regular file (${st.isDirectory() ? 'directory' : 'special file'})`);
}
}
// before creating the store:
assertDbPathUsable(dbPath); Type guard
function isRegularFileOrMissing(p) {
const st = fs.lstatSync(p, { throwIfNoEntry: false });
return st === undefined || st.isFile();
} Try / catch
try {
const store = await createStateStore({ dbPath });
} catch (error) {
if (error.message.includes('database path is not a regular file')) {
const st = fs.lstatSync(dbPath, { throwIfNoEntry: false });
if (st && st.isDirectory()) fs.rmSync(dbPath, { recursive: true });
// retry
} else {
throw error;
}
} Prevention
- Always pass a file path (ending in a filename like state.db), never a directory, as dbPath
- Before first use, check with fs.lstatSync that an existing dbPath is a regular file and not a symlink
- Avoid placing the database where sockets/FIFOs are created (IPC dirs, tmp mount points)
- Give each concurrent process/test its own dbPath to prevent path collisions
When it happens
Trigger: createStateStore({ dbPath }) where dbPath already exists as a directory (e.g. someone pre-created state.db as a folder, or passed a directory path as dbPath), or as any non-regular file (FIFO, socket). Triggered from openDatabase, writeDatabaseFileAtomic (first saveToDisk), or readDatabaseFile — the check throws before any I/O on the path.
Common situations: Passing a directory instead of a file path to dbPath (e.g. createStateStore({ dbPath: someDir }) instead of path.join(someDir, 'state.db')), a mount point named state.db, a tmpfs/IPC socket placed at the db path, or tooling that created the path as a directory on first run.
Related errors
- Unsafe state-store path
- Refusing to : missing destination path.
- all overlays must be readable local files
- all takes must be readable local files
- artifact path must stay beneath output root
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/6c2d9628e04bf19c.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/state-store/index.js:106
}
}
stats = fs.lstatSync(currentPath);
assertNotSymlink(currentPath, stats);
}
if (!stats.isDirectory() && !isAllowedPlatformSymlink(currentPath, stats)) {
throw stateStorePathError(currentPath, 'an intermediate component is not a directory');
}
}
return absolutePath;
}
function assertSafeDatabaseFile(dbPath) {
const stats = lstatIfPresent(dbPath);
assertNotSymlink(dbPath, stats);
if (stats && !stats.isFile()) {
throw stateStorePathError(dbPath, 'database path is not a regular file');
}
return stats;
}
function readDatabaseFile(dbPath) {
assertSafeDatabaseFile(dbPath);
const noFollow = fs.constants.O_NOFOLLOW || 0;
const fileDescriptor = fs.openSync(dbPath, fs.constants.O_RDONLY | noFollow);
try {
const stats = fs.fstatSync(fileDescriptor);
if (!stats.isFile()) {
throw stateStorePathError(dbPath, 'database path is not a regular file');
}
return fs.readFileSync(fileDescriptor);
} finally {
fs.closeSync(fileDescriptor);
}
}View on GitHub (pinned to 8321021c54)