affaan-m/ECC · error · Error
ECC_MEMORY_INCOMPLETE
ECC_MEMORY_INCOMPLETE
Error message
Memory lookup is incomplete. Inspect the authorized vault before retrying.
What it means
readMemoryFiles in scripts/lib/memory-vault.js walks each authorized vault scope root with walkMemoryRoot to build a complete index of memory documents. If the walk itself throws (a directory could not be opened, read, or closed), the library cannot prove the lookup saw every file, so it throws ECC_MEMORY_INCOMPLETE instead of returning silently partial results.
Solutions
- Fix filesystem access to the vault directory: check permissions with ls -la on ~/.claude (or the configured roots) and restore read/execute for your user.
- Retry the lookup — transient EIO from a network/encrypted filesystem often resolves on a second attempt.
- Verify the configured vault roots exist and are real directories; recreate a missing scope directory.
- Check for processes deleting/moving vault directories concurrently and pause them during lookups.
Example fix
// before: vault subdir unreadable -> ECC_MEMORY_INCOMPLETE
// drwx------ someuser staff memory/ but process runs as other user
sudo chown -R $(whoami) ~/.claude/ecc/memory
// after: lookup completes
const loaded = readMemoryFiles({ scopes: ['project'] }); Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require('fs');
function vaultIsReadable(root) {
try { fs.accessSync(root, fs.constants.R_OK | fs.constants.X_OK); return true; }
catch { return false; }
} Type guard
function canWalk(dir) {
try { return fs.statSync(dir).isDirectory() && fs.accessSync(dir, fs.constants.R_OK) === undefined; }
catch { return false; }
} Try / catch
try {
const results = searchMemories(query, { scopes: ['project'] });
} catch (e) {
if (e.code === 'ECC_MEMORY_INCOMPLETE') {
console.error('Vault unreadable; check permissions on the memory root, then retry.');
} else throw e;
} Prevention
- Keep the vault root and subdirectories owned and readable by the user running ECC.
- Avoid storing the memory vault on flaky network/encrypted mounts.
- Don't delete or move vault directories while lookups are running.
When it happens
Trigger: readMemoryFiles (via searchMemories/loaded) calls walkMemoryRoot(root, budget) and the walk throws — e.g. EACCES/EIO opening or reading a subdirectory of the vault root, or a scope root disappearing between assertMemoryRootSafe and the walk.
Common situations: Vault directory permissions changed (chmod/chown, restrictive umask); an OS-level I/O error on a networked or encrypted home directory; another process deleting a scope directory mid-lookup; running as a different user than the vault owner.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Cannot create exclusive receipt
- Cannot read local asset
- Failed to create directory
- destination is not writable by the current user: . Fix the…
- local artifact unavailable or unsafe
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/a6bf75f181315d91.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/memory-vault.js:475
const skippedSymlinks = [];
let invalidFileCount = 0;
let skippedSymlinkCount = 0;
let visitedCount = 0;
let scannedBytes = 0;
let truncated = false;
for (const scope of scopes) {
if (visitedCount >= MAX_FILES || scannedBytes >= MAX_SCAN_BYTES) {
truncated = true;
break;
}
const root = assertMemoryRootSafe(roots, scope);
let walked;
try {
walked = walkMemoryRoot(root, MAX_FILES - visitedCount);
} catch {
// Directory open/read/close failures cannot establish a complete lookup.
throw incompleteMemoryLookupError();
}
visitedCount += walked.visitedCount;
truncated = truncated || walked.truncated;
skippedSymlinkCount += walked.skippedSymlinkCount;
for (const skippedPath of walked.skippedSymlinks) {
if (skippedSymlinks.length >= MAX_DIAGNOSTICS) break;
skippedSymlinks.push(vaultRelativePath(scope, root, skippedPath));
}
for (const filePath of walked.paths) {
if (scannedBytes >= MAX_SCAN_BYTES) {
truncated = true;
break;
}
try {
const source = readRegularTextFile(filePath, {
label: 'memory document',
maxBytes: MAX_DOCUMENT_BYTES,View on GitHub (pinned to 8321021c54)