{"record":{"id":"f0359b2e59d4172a","repo":"nanocoai/nanoclaw","slug":"stdin-json-input-exceeds-max-stdin-json-bytes-f0359b","errorCode":null,"errorMessage":"--stdin-json input exceeds ${MAX_STDIN_JSON_BYTES} bytes","messagePattern":"--stdin-json input exceeds (.+?) bytes","errorType":"validation","errorClass":"StdinJsonInputError","httpStatus":null,"severity":"error","filePath":"src/cli/stdin-json.ts","lineNumber":54,"sourceCode":" * therefore normalized to a Buffer and the running total counts\n * `buffer.byteLength` — the true encoded size — rather than string length,\n * where a multibyte character (e.g. \"ש\", 2 bytes) would count as 1.\n *\n * Decoding to text happens exactly once, after the whole input is collected:\n * a chunk boundary can fall in the middle of a multibyte character, so\n * decoding chunk-by-chunk could corrupt the character that straddles the\n * split. The limit check runs before buffering grows past the cap, so an\n * oversized (or unbounded) pipe is rejected without being read to the end.\n */\nasync function readBounded(stream: StdinJsonStream): Promise<string> {\n  const chunks: Buffer[] = [];\n  let byteLength = 0;\n\n  for await (const chunk of stream) {\n    const buffer = typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : Buffer.from(chunk);\n    byteLength += buffer.byteLength;\n    if (byteLength > MAX_STDIN_JSON_BYTES) {\n      throw new StdinJsonInputError(`--stdin-json input exceeds ${MAX_STDIN_JSON_BYTES} bytes`);\n    }\n    chunks.push(buffer);\n  }\n\n  return Buffer.concat(chunks, byteLength).toString('utf8');\n}\n\n/** Parse the input, requiring exactly one JSON object — not an array, scalar, or null. */\nfunction parseJsonObject(source: string): Record<string, unknown> {\n  if (source.trim().length === 0) {\n    throw new StdinJsonInputError('--stdin-json input is empty');\n  }\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(source);\n  } catch (err) {\n    throw new StdinJsonInputError('--stdin-json input is not valid JSON', { cause: err });","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/cli/stdin-json.ts#L36-L72","documentation":"readBounded streams stdin for --stdin-json and enforces MAX_STDIN_JSON_BYTES; exceeding the cap aborts before parsing to bound memory use.","triggerScenarios":"Piping a JSON document larger than MAX_STDIN_JSON_BYTES to `ncl ... --stdin-json` (e.g. a huge embedded payload, base64 blob, or accidental binary file).","commonSituations":"Embedding large assets in a create/update payload, or accidentally piping a log/CSV instead of the intended small object.","solutions":["Shrink the payload — remove large blobs or move big data to a file path the command references instead","Split into multiple smaller operations","Pipe the correct, intended JSON file"],"exampleFix":"# before\ncat huge-payload.json | ncl groups update --id g1 --stdin-json\n# after\nncl groups update --id g1 --name newname","handlingStrategy":"validation","validationCode":"const size = fs.statSync(path).size;\nif (size > MAX_STDIN_JSON_BYTES) throw new Error('payload too large; move data to a file path');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep --stdin-json payloads to plain args, not embedded blobs"],"tags":["cli","stdin-json","size-limit"],"backgroundTag":"payload-too-large","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}