affaan-m/ECC · error · Error
Choose exactly one memory body source: --stdin or…
Error message
Choose exactly one memory body source: --stdin or --body-file.
What it means
readBody requires exactly one memory body source: the CLI must receive either --stdin or --body-file, never both and never neither. It counts the truthy flags (filter(Boolean).length) and throws when the count is not 1. This removes ambiguity about where the memory content comes from.
Solutions
- Pass exactly one source: either pipe content with `--stdin` or point `--body-file <path>` at an existing file, not both.
- If you have both flags set by a wrapper script, strip one: choose --body-file for reproducible scripts, --stdin for ad-hoc pipes.
- For empty/missing input, provide a file even if minimal rather than invoking with zero sources.
- Wrap flag assembly in a small helper that asserts exactly one of the two flags is present before exec.
Example fix
// before echo "notes" | node scripts/memory.js save --stdin --body-file notes.md --title t // after echo "notes" | node scripts/memory.js save --stdin --title t
Defensive patterns
Strategy: validation
Validate before calling
const sourceCount = [Boolean(opts.stdin), Boolean(opts.bodyFile)].filter(Boolean).length;
if (sourceCount !== 1) throw new Error('Provide exactly one of --stdin or --body-file.'); Type guard
function hasExactlyOneBodySource(o) {
return (typeof o.stdin === 'boolean') + (typeof o.bodyFile === 'string') === 1;
} Try / catch
try {
readBody(options);
} catch (err) {
if (String(err.message).startsWith('Choose exactly one memory body source')) {
console.error('Pass either --stdin (piped) or --body-file <path>, not both/neither.');
} else throw err;
} Prevention
- Standardize scripts on --body-file for reproducibility; reserve --stdin for interactive pipes.
- Build CLI flags in one place so both flags can never be appended simultaneously.
- Never invoke save/write commands without a body source; validate flags before exec.
When it happens
Trigger: Running a save/write memory command with neither --stdin nor --body-file (sources === 0), or passing both flags in the same invocation (sources === 2). Raised in readBody, called from saveInput.
Common situations: Forgetting to redirect stdin (running `memory save --stdin` with no pipe AND no body); copy-pasting example commands that combine flags; shell scripts that conditionally add --stdin but leave --body-file set from a shared flag list.
Understand the failure class
Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.
Related errors
- graph sync does not accept a session ID when --all is set
- --all-harnesses and --harness are mutually exclusive.
- Choose only one output format: --json or --markdown
- Conflict messages require at least one --file
- connector name required unless --all is set
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/c6daa25d6abb1533.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/memory.js:197
wait(retryDelayMs);
remainingRetryWaitMs -= retryDelayMs;
continue;
}
if (bytesRead === 0) break;
chunks.push(buffer.subarray(0, bytesRead));
total += bytesRead;
}
if (total > maxBytes) {
throw new Error(`memory body is too large (maximum ${maxBytes} bytes).`);
}
return decodeUtf8(Buffer.concat(chunks, total), 'memory body from standard input');
}
function readBody(options) {
const sources = [Boolean(options.stdin), Boolean(options.bodyFile)]
.filter(Boolean).length;
if (sources !== 1) {
throw new Error('Choose exactly one memory body source: --stdin or --body-file.');
}
if (options.stdin) {
return readBoundedStdin(MAX_BODY_BYTES);
}
const bodyPath = path.resolve(options.bodyFile);
return readRegularTextFile(bodyPath, {
label: '--body-file',
maxBytes: MAX_BODY_BYTES,
});
}
function writeJson(payload) {
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
}
function skipTerminalString(value, offset) {
let index = offset;View on GitHub (pinned to 8321021c54)