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

  1. Pass exactly one source: either pipe content with `--stdin` or point `--body-file <path>` at an existing file, not both.
  2. If you have both flags set by a wrapper script, strip one: choose --body-file for reproducible scripts, --stdin for ad-hoc pipes.
  3. For empty/missing input, provide a file even if minimal rather than invoking with zero sources.
  4. 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

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


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)