{"record":{"id":"6092b93aabf57078","repo":"affaan-m/ECC","slug":"read-requires-exactly-one-memory-id","errorCode":null,"errorMessage":"read requires exactly one memory ID.","messagePattern":"read requires exactly one memory ID\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/memory.js","lineNumber":440,"sourceCode":"    saveMemory(saveInput(options, command === 'handoff' ? 'handoff' : null), { roots }),\n    options.json\n  );\n}\n\nfunction runSearchCommand({ options, positionals, roots }) {\n  const query = positionals.join(' ');\n  return printSearch(query, searchMemories(query, {\n    roots,\n    scopes: options.scopes,\n    kinds: options.kinds,\n    targetHarness: options.targetHarness,\n    limit: options.limit,\n  }), options.json);\n}\n\nfunction runReadCommand({ options, positionals, roots }) {\n  if (positionals.length !== 1) {\n    throw new Error('read requires exactly one memory ID.');\n  }\n  return printRead(readMemoryById(positionals[0], {\n    roots,\n    scopes: options.scopes,\n  }), options.json);\n}\n\nfunction runDoctorCommand({ command, options, positionals, roots }) {\n  requireNoPositionals(positionals, command);\n  return printDoctor(doctorMemoryVault({\n    roots,\n    scopes: options.scopes,\n  }), options.json);\n}\n\nconst COMMAND_HANDLERS = Object.freeze({\n  doctor: runDoctorCommand,\n  handoff: runWriteCommand,","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/memory.js#L422-L458","documentation":"Thrown by runReadCommand in scripts/memory.js when the `read` subcommand does not receive exactly one positional argument (the memory ID). The read operation targets a single memory record, so zero IDs or multiple IDs are both rejected — passing two IDs does not read two memories.","triggerScenarios":"Running `node scripts/memory.js read` with no ID, or `node scripts/memory.js read id1 id2`. The check is `positionals.length !== 1`, so any count other than one triggers it. Positionals are the non-flag trailing arguments after command parsing.","commonSituations":"Forgetting the ID when building a quick lookup; pasting a space-separated list of IDs expecting batch reads; a shell variable that expands to empty or to multiple words; confusing `read` (single ID) with `search` (free-text query from positionals).","solutions":["Pass exactly one memory ID: `node scripts/memory.js read <id>`.","To find an ID first, run `search` with a query, then `read` the returned ID.","Quote shell variables (`\"$ID\"`) so an unset variable produces zero args you can detect, rather than silently shifting positionals."],"exampleFix":"// before\nnode scripts/memory.js read 2024-01-15-meeting 2024-01-16-notes\n// after\nnode scripts/memory.js read 2024-01-15-meeting","handlingStrategy":"validation","validationCode":"function assertSingleId(positionals) {\n  if (!Array.isArray(positionals) || positionals.length !== 1) {\n    throw new Error(`read expects exactly one memory ID, got ${positionals ? positionals.length : 0}`);\n  }\n  return positionals[0];\n}","typeGuard":"function isSingleId(positionals) {\n  return Array.isArray(positionals) && positionals.length === 1 && typeof positionals[0] === 'string' && positionals[0].length > 0;\n}","tryCatchPattern":null,"preventionTips":["Quote shell variables holding an ID so word-splitting cannot turn one ID into zero or many positionals.","Use `search` for lookups and reserve `read` for a single known ID.","In batch tooling, loop over IDs and call read once each rather than passing a list."],"tags":["cli","memory","argument-validation"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}