affaan-m/ECC · error · Error
message
Error message
message
What it means
assertMemoryRootSafe looks up roots[scope] and requires it to be a non-empty string path. If the scope key is absent or its value is empty/not a string, the vault cannot know where to store memory for that scope and throws this error naming the scope. This is thrown before any filesystem access occurs.
Solutions
- Add the missing scope with a valid absolute directory path to the roots configuration.
- Fix the scope name passed to the vault call so it matches a key defined in roots.
- Verify the value is a non-empty string, not null/undefined/number.
- Synchronize scope constants between caller code and the config file to prevent drift.
Example fix
// before (config)
{ project: '/vault/project' } // no 'personal' scope
resolveMemoryRoot(roots, 'personal');
// after
{ project: '/vault/project', personal: '/vault/personal', [VAULT_ROOT_BOUNDARIES]: { project: '/vault/project', personal: '/vault/personal' } } Defensive patterns
Strategy: validation
Validate before calling
function assertScopeConfigured(roots, scope) {
const root = roots?.[scope];
if (typeof root !== 'string' || root.length === 0) {
throw new Error(`Scope "${scope}" has no memory root configured. Add it to your roots config.`);
}
} Type guard
const hasScopeRoot = (roots, scope) => typeof roots?.[scope] === 'string' && roots[scope].length > 0;
Try / catch
try {
const root = resolveMemoryRoot(roots, scope);
} catch (err) {
if (err.message.startsWith('No memory root is configured')) {
throw new Error(`Unknown memory scope "${scope}". Configured scopes: ${Object.keys(roots).filter(k => k !== '__boundaries').join(', ')}`);
}
throw err;
} Prevention
- Import scope names from shared constants instead of typing strings at call sites.
- List all available scopes in config docs and error output.
- Add a startup check that every scope used by the codebase exists in the config.
- Watch for case/typo mismatches between call sites and config keys.
When it happens
Trigger: Requesting a scope (e.g. 'personal', 'project') that is not present in the roots config object, or whose value is '' or a non-string (number, null). Also occurs when the config defines the scope under a differently-cased or misspelled key.
Common situations: Typos in the scope name at the call site ('Project' vs 'project'); a fresh install where the config template only defines some scopes; an environment-specific config that omits a scope; a renamed scope constant not updated everywhere.
Related errors
- ECC_PROJECT_DIR must be a child path within /workspace.
- Unknown argument
- Announcements discussion category is required
- Choose at least one guided harness: Claude, Codex, or Kimi.
- config must be a JSON object
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/ac205db5ea1b00af.
Report an issue: GitHub.
Appendix: source
Thrown at docker/plugin-setup/verify-install-plan.js:9
#!/usr/bin/env node
'use strict';
const fs = require('fs');
const path = require('path');
function fail(message) {
throw new Error(message);
}
function isWithin(root, candidate) {
const relative = path.relative(root, candidate);
return relative === '' || (
relative !== '..'
&& !relative.startsWith(`..${path.sep}`)
&& !path.isAbsolute(relative)
);
}
function validatePlan(payload, projectDir, requireDryRun) {
const expectedRoot = path.resolve(projectDir, '.claude');
if (!payload || typeof payload !== 'object' || !payload.plan) {
fail('Install output is missing a plan.');
}
if (requireDryRun && payload.dryRun !== true) {
fail('Install plan did not report dryRun=true.');View on GitHub (pinned to 8321021c54)