affaan-m/ECC · error · Error

No memory root is configured for scope "${scope}".

Error message

No memory root is configured for scope "${scope}".

What it means

Thrown by assertMemoryRootSafe() when roots[scope] is not a non-empty string. The three valid scopes are 'project', 'team', and 'user' (the keys produced by resolveVaultRoots()). A scope typo, a scope that the roots object was not built to handle, or a roots object missing a key triggers this. The error includes the bad scope in the message.

Source

Thrown at scripts/lib/memory-vault.js:103

        : projectRoot,
      user: env.ECC_MEMORY_USER_ROOT
        ? realpathNearestExisting(userVault)
        : homeDir,
    }),
    enumerable: false,
    configurable: false,
    writable: false,
  });
  return Object.freeze(roots);
}

function assertMemoryRootSafe(roots, scope) {
  if (!roots || typeof roots !== 'object' || Array.isArray(roots)) {
    throw new Error('Memory roots must include a trusted boundary policy.');
  }
  const root = roots[scope];
  if (typeof root !== 'string' || root.length === 0) {
    throw new Error(`No memory root is configured for scope "${scope}".`);
  }
  const boundary = roots[VAULT_ROOT_BOUNDARIES]?.[scope];
  if (typeof boundary !== 'string' || boundary.length === 0) {
    throw new Error(`No trusted boundary policy is configured for memory scope "${scope}".`);
  }
  assertWithinTrustedRoot(root, boundary, 'access memory through a symlink');
  if (fs.existsSync(root) && fs.lstatSync(root).isSymbolicLink()) {
    throw new Error(`Refusing to access memory through symlink root: ${root}`);
  }
  return root;
}

function assertMemoryDirectorySafe(directory, root) {
  assertWithinTrustedRoot(directory, root, 'access memory directory');
  if (fs.existsSync(directory) && fs.lstatSync(directory).isSymbolicLink()) {
    throw new Error(`Refusing to access memory through symlink directory: ${directory}`);
  }
  return directory;

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Use one of the exported MEMORY_SCOPES: 'project', 'team', or 'user'.
  2. When constructing scopes, use normalizeScopes() — it validates against MEMORY_SCOPES.
  3. Pass options.scopes as MEMORY_SCOPES or DEFAULT_RECALL_SCOPES rather than hard-coding.
  4. Inspect the scope value printed in the error message and align it with the canonical names.

Example fix

// before
readMemoryFiles({ scopes: ['projct'] }); // typo
saveMemory({ scope: 'workspace', body: '...' }); // unknown scope

// after
const { MEMORY_SCOPES } = require('./scripts/lib/memory-vault');
readMemoryFiles({ scopes: MEMORY_SCOPES });
saveMemory({ scope: 'project', body: '...' });
Defensive patterns

Strategy: validation

Validate before calling

const { MEMORY_SCOPES } = require('./scripts/lib/memory-vault');
const scope = input.scope;
if (!MEMORY_SCOPES.includes(scope)) {
  throw new Error(`scope must be one of ${MEMORY_SCOPES.join(', ')}; got ${scope}`);
}
saveMemory(input);

Type guard

const MEMORY_SCOPES = ['project','team','user'] as const;
function isMemoryScope(value): value is typeof MEMORY_SCOPES[number] {
  return MEMORY_SCOPES.includes(value);
}

Prevention

When it happens

Trigger: readMemoryFiles({scopes: ['projct']}) (typo), assertMemoryRootSafe(roots, 'org') when 'org' is not a configured scope, calling saveMemory({scope: 'workspace'}) with an unsupported scope, or a custom roots object built without the 'team' key when team scope is requested.

Common situations: Caller uses a different taxonomy of scopes than the library expects. Configuration drift where a custom roots builder omitted a key. Test fixture that only set up 'project' and 'user' but the test ran over 'team'.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/f7e07b377a2dc468. Report an issue: GitHub.