affaan-m/ECC · error · Error

Project memory .gitignore does not contain the required…

Error message

Project memory .gitignore does not contain the required fail-closed rules.

What it means

ensureProjectScopeIgnored verifies that the project memory directory's .gitignore exactly matches the library's required fail-closed content (PROJECT_MEMORY_GITIGNORE). If a pre-existing .gitignore differs at all, it throws this error rather than silently overwriting user content. This guarantees project-scope memories are never committed to git.

Solutions

  1. Delete the existing .gitignore in the project memory directory so the library recreates it with the required rules.
  2. Or replace its content with the exact canonical PROJECT_MEMORY_GITIGNORE text.
  3. Check git history of the vault to see what changed and restore the canonical content.

Example fix

// before (edited .gitignore)
# my notes
*
// after
cat scripts/lib/memory-vault.js | grep -A5 PROJECT_MEMORY_GITIGNORE  # copy exact content into the vault .gitignore, or: rm <vault>/project/.gitignore
Defensive patterns

Strategy: validation

Validate before calling

const expected = PROJECT_MEMORY_GITIGNORE; // canonical content from the library
const current = fs.readFileSync(path.join(vaultProjectDir, '.gitignore'), 'utf8');
if (current !== expected) fs.writeFileSync(path.join(vaultProjectDir, '.gitignore'), expected);

Try / catch

try {
  saveMemory(memory);
} catch (err) {
  if (err.message.includes('fail-closed rules')) {
    // restore canonical .gitignore, then retry the save
  } else throw err;
}

Prevention

When it happens

Trigger: Calling saveMemory or directories for a project-scoped memory when a .gitignore already exists in the project memory directory but its content differs from the canonical PROJECT_MEMORY_GITIGNORE string.

Common situations: A user or tool manually edited the vault .gitignore (added comments, different rules); an older library version wrote a different .gitignore format and the library was upgraded; a formatter normalized the file (trailing newline changes).

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

  if (operationError) throw operationError;
  if (cleanupError) throw cleanupError;
}

function ensureProjectScopeIgnored(roots, scope) {
  if (scope !== 'project') return;
  const root = roots.project;
  const ignorePath = path.join(root, '.gitignore');
  try {
    writeCreateOnlyTextFile(ignorePath, PROJECT_MEMORY_GITIGNORE, root);
  } catch (error) {
    if (!error || error.code !== 'EEXIST') throw error;
    const existing = readRegularTextFile(ignorePath, {
      label: 'project memory .gitignore',
      maxBytes: MAX_DOCUMENT_BYTES,
      trustedRoot: root,
    });
    if (existing !== PROJECT_MEMORY_GITIGNORE) {
      throw new Error(
        'Project memory .gitignore does not contain the required fail-closed rules.'
      );
    }
  }
}

function normalizeScopes(scopes = MEMORY_SCOPES) {
  const values = Array.isArray(scopes) ? scopes : [scopes];
  return uniqueStrings(values, {
    label: 'scopes',
    limit: MEMORY_SCOPES.length,
    validator: value => validateEnum(value, MEMORY_SCOPES, 'memory scope'),
  });
}

function initializeVault(options = {}) {
  const roots = options.roots || resolveVaultRoots(options);
  const scopes = normalizeScopes(options.scopes || DEFAULT_RECALL_SCOPES);

View on GitHub (pinned to 8321021c54)