affaan-m/ECC · error · Error

Refusing to save memory containing a suspected secret (${sec

Error message

Refusing to save memory containing a suspected secret (${secretKinds.join(', ')}).

What it means

Before persisting, saveMemory serializes the normalized memory to JSON and runs findPotentialSecrets across the whole document. If any substring matches a known secret pattern (API keys, tokens, private keys, etc.), the save is refused outright — the vault is designed never to store secrets, so this is a hard stop, not a warning. The secret kinds are listed in the message.

Source

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

    scope: input.scope || 'project',
    trust: 'unreviewed',
    status: 'active',
    sourceHarness: input.sourceHarness || 'unknown',
    targetHarnesses: input.targetHarnesses || ['all'],
    tags: input.tags || [],
    links: input.links || [],
    createdAt: now,
    updatedAt: now,
    body: input.body || '',
  });
}

function saveMemory(input, options = {}) {
  const roots = options.roots || resolveVaultRoots(options);
  const memory = normalizeSaveInput(input || {}, options);
  const secretKinds = findPotentialSecrets(JSON.stringify(memory));
  if (secretKinds.length > 0) {
    throw new Error(`Refusing to save memory containing a suspected secret (${secretKinds.join(', ')}).`);
  }

  const root = assertMemoryRootSafe(roots, memory.scope);
  fs.mkdirSync(root, { recursive: true, mode: 0o700 });
  ensureProjectScopeIgnored(roots, memory.scope);
  const directory = path.join(root, `${memory.kind}s`);
  assertMemoryDirectorySafe(directory, root);
  fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
  const destination = path.join(directory, `${memory.id}.md`);

  try {
    writeCreateOnlyTextFile(destination, serializeMemoryDocument(memory), root);
  } catch (error) {
    if (error && error.code === 'EEXIST') {
      throw new Error(`Memory ${memory.id} already exists; writes are create-only.`);
    }
    throw error;
  }

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Remove the secret from the memory body and reference it by name only (e.g. 'uses OPENAI_API_KEY from the env') — never paste the value.
  2. Store the actual secret in a dedicated secret manager (env var, vault, keychain) and keep only its identifier in the memory.
  3. If the heuristic is flagging a false positive (a long high-entropy string that is not a secret), restructure the content so it does not match (split it, describe it, or store an identifier instead of the raw value).
  4. Audit the body, title, tags, and links fields — the check scans all of them via JSON.stringify.

Example fix

// before
saveMemory({ title: 'deploy token', body: 'ghp_abcdefghijklmnopqrstuvwxyz1234' });
// after
saveMemory({ title: 'deploy token', body: 'The deploy token is stored in GH_DEPLOY_TOKEN (1Password). Rotate quarterly.' });
Defensive patterns

Strategy: validation

Validate before calling

const { findPotentialSecrets } = require('./scripts/lib/memory-vault');
function assertNoSecrets(memory) {
  const kinds = findPotentialSecrets(JSON.stringify(memory));
  if (kinds.length > 0) {
    throw new Error(`Refusing to save memory containing a suspected secret (${kinds.join(', ')}).`);
  }
}
// before saveMemory:
assertNoSecrets(normalizeMemory(input));

Try / catch

try { saveMemory(input); }
catch (error) {
  if (/suspected secret/i.test(error.message)) {
    console.error('Strip secrets from the memory body/title/tags/links:', error.message);
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling saveMemory with a body, title, tags, or links field that contains a string matching a secret heuristic (e.g. an OpenAI sk- key, a GitHub PAT, an AWS secret access key, a PEM private key block, a JWT). The check runs on JSON.stringify(memory), so secrets hidden anywhere in the object are caught.

Common situations: Pasting an API key into a memory body as a 'note to self'; storing a .env excerpt; recording a curl command that includes a Bearer token; capturing an error message that logged a secret; a stack trace containing decrypted credentials.

Related errors


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