affaan-m/ECC · error · Error

Unknown argument

Error message

Unknown argument: ${arg}

What it means

Each scope root must be paired with a trusted boundary policy string under roots[VAULT_ROOT_BOUNDARIES][scope]; that boundary defines the trusted filesystem region the root must stay inside. If the boundary is missing, empty, or not a string, assertMemoryRootSafe throws this error. The library refuses to operate without an explicit trust boundary so symlink and path-escape attacks cannot bypass containment.

Solutions

  1. Add a trusted boundary path for the scope under roots[VAULT_ROOT_BOUNDARIES][scope] (the boundary must contain the scope root).
  2. Set the boundary to the same directory as the root (or a parent of it) if the whole root directory is trusted.
  3. Validate the roots object on startup with a check that iterates all scopes and asserts each has a non-empty boundary.
  4. Regenerate the config from the installer/template that emits both roots and boundaries together.

Example fix

// before
const roots = { project: '/vault/project' };

// after
const roots = {
  project: '/vault/project',
  [VAULT_ROOT_BOUNDARIES]: { project: '/vault/project' }
};
Defensive patterns

Strategy: validation

Validate before calling

const VAULT_ROOT_BOUNDARIES = '__boundaries'; // match the library's key
function assertBoundariesPresent(roots, scopes) {
  for (const scope of scopes) {
    const b = roots?.[VAULT_ROOT_BOUNDARIES]?.[scope];
    if (typeof b !== 'string' || b.length === 0) {
      throw new Error(`Scope "${scope}" is missing its trusted boundary policy in ${VAULT_ROOT_BOUNDARIES}.`);
    }
  }
}

Type guard

const hasBoundary = (roots, scope) => typeof roots?.[VAULT_ROOT_BOUNDARIES]?.[scope] === 'string' && roots[VAULT_ROOT_BOUNDARIES][scope].length > 0;

Try / catch

try {
  const root = resolveMemoryRoot(roots, scope);
} catch (err) {
  if (err.message.includes('trusted boundary policy is configured')) {
    throw new Error(`Add ${scope} to the boundary map in your memory roots config.`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Providing a roots object that maps scope -> path but omits the corresponding entry in the VAULT_ROOT_BOUNDARIES map, sets it to '' or null, or builds the boundaries object dynamically and the scope key never got inserted.

Common situations: Hand-writing the roots config and adding a new scope path without adding its boundary entry; a migration that renamed VAULT_ROOT_BOUNDARIES or restructured the config; copying a scope entry without its boundary counterpart; programmatically generated config where a loop skipped one scope.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/926789182a1251fe. Report an issue: GitHub.

Appendix: source

Thrown at scripts/auto-update.js:48

  };

  for (let index = 0; index < args.length; index += 1) {
    const arg = args[index];

    if (arg === '--target') {
      parsed.targets.push(args[index + 1] || null);
      index += 1;
    } else if (arg === '--repo-root') {
      parsed.repoRoot = args[index + 1] || null;
      index += 1;
    } else if (arg === '--dry-run') {
      parsed.dryRun = true;
    } else if (arg === '--json') {
      parsed.json = true;
    } else if (arg === '--help' || arg === '-h') {
      parsed.help = true;
    } else {
      throw new Error(`Unknown argument: ${arg}`);
    }
  }

  return parsed;
}

function deriveRepoRootFromState(state) {
  const operations = Array.isArray(state && state.operations) ? state.operations : [];

  for (const operation of operations) {
    if (typeof operation.sourcePath !== 'string' || !operation.sourcePath.trim()) {
      continue;
    }

    if (typeof operation.sourceRelativePath !== 'string' || !operation.sourceRelativePath.trim()) {
      continue;
    }

View on GitHub (pinned to 8321021c54)