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
- 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.
- Store the actual secret in a dedicated secret manager (env var, vault, keychain) and keep only its identifier in the memory.
- 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).
- 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
- Never paste secret values into a memory — reference them by env var name instead.
- Run input through findPotentialSecrets in a pre-save hook to fail early.
- Audit memory bodies, titles, tags, and links — the check scans the whole serialized object.
- Store real secrets in a dedicated secret manager (1Password, env, keychain).
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
- ${label} must not contain control or bidirectional formattin
- memory body must not contain unsafe control or bidirectional
- No trusted boundary policy is configured for memory scope "$
- ${label} must be a regular, non-symlink file.
- Project memory .gitignore does not contain the required fail
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/76d1d93fd780ccdd.
Report an issue: GitHub.