affaan-m/ECC · warning · Error

Choose exactly one memory body source: --stdin or --body-fil

Error message

Choose exactly one memory body source: --stdin or --body-file.

What it means

readBody counts how many of --stdin and --body-file are truthy and requires exactly one; zero sources or both sources throws `Choose exactly one memory body source: --stdin or --body-file.` The XOR guard prevents ambiguity about where the memory body comes from and avoids silent precedence surprises.

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 01e15490f0)

Solutions

  1. Always supply exactly one body source per save/handoff.
  2. For interactive use, prefer `--body-file <path>` to avoid TTY/stdin issues.
  3. For piped content, use only `--stdin`.
  4. Audit shell aliases/wrappers to ensure they do not auto-inject a second source.

Example fix

# before
ecc memory save --title "notes"   # no body source
# or
ecc memory save --title "notes" --stdin --body-file notes.md

# after — exactly one source
ecc memory save --title "notes" --body-file notes.md
Defensive patterns

Strategy: validation

Validate before calling

function assertExactlyOneBodySource(options) {
  const n = [Boolean(options.stdin), Boolean(options.bodyFile)].filter(Boolean).length;
  if (n !== 1) throw new Error('Choose exactly one memory body source: --stdin or --body-file.');
}

Try / catch

try { body = readBody(options); }
catch (err) { if (/Choose exactly one memory body source/.test(err.message)) { usage(2); } else throw err; }

Prevention

When it happens

Trigger: Calling `memory save --title x` with neither --stdin nor --body-file. Passing both: `memory save --title x --stdin --body-file notes.md`. A wrapper that always adds --stdin but the user also passed --body-file.

Common situations: Forgetting the body source entirely (most common). A default --stdin in an alias colliding with an explicit --body-file. Interactive use where neither pipe nor file was set up.

Related errors


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