{"record":{"id":"bd5663712216302d","repo":"affaan-m/ECC","slug":"label-is-too-large-maximum-maxbytes-bytes","errorCode":null,"errorMessage":"${label} is too large (maximum ${maxBytes} bytes).","messagePattern":"(.+?) is too large \\(maximum (.+?) bytes\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/memory-vault.js","lineNumber":183,"sourceCode":"    }\n    if (options.trustedRoot) {\n      assertWithinTrustedRoot(filePath, options.trustedRoot, `read ${label}`);\n    }\n    if (opened.size > BigInt(maxBytes)) {\n      throw new Error(`${label} is too large (${opened.size} bytes).`);\n    }\n\n    const chunks = [];\n    let total = 0;\n    while (total <= maxBytes) {\n      const buffer = Buffer.alloc(Math.min(64 * 1024, maxBytes + 1 - total));\n      const bytesRead = fs.readSync(descriptor, buffer, 0, buffer.length, null);\n      if (bytesRead === 0) break;\n      chunks.push(buffer.subarray(0, bytesRead));\n      total += bytesRead;\n    }\n    if (total > maxBytes) {\n      throw new Error(`${label} is too large (maximum ${maxBytes} bytes).`);\n    }\n    return decodeUtf8(Buffer.concat(chunks, total), label);\n  } finally {\n    fs.closeSync(descriptor);\n  }\n}\n\nfunction writeCreateOnlyTextFile(filePath, content, trustedRoot) {\n  assertWithinTrustedRoot(filePath, trustedRoot, 'write memory');\n  const temporaryPath = path.join(\n    path.dirname(filePath),\n    `.ecc-memory-${process.pid}-${crypto.randomUUID()}.tmp`\n  );\n  const flags = fs.constants.O_WRONLY\n    | fs.constants.O_CREAT\n    | fs.constants.O_EXCL\n    | (fs.constants.O_NOFOLLOW || 0);\n  let descriptor;","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/memory-vault.js#L165-L201","documentation":"Even when the file was small enough at open time, readRegularTextFile streams in 64KB chunks and re-asserts the cap after reading. If the file grew between the fstat size check and the read loop so that total bytes read exceeds maxBytes, the read is aborted. This catches an attacker (or a concurrent appender) who grows the file mid-read to bypass the static size check.","triggerScenarios":"A file whose size at fstat was <= maxBytes but which was appended to during the read loop, pushing total bytes read past maxBytes. Caused by a concurrent writer appending to a memory file, a logging-style memory that is being actively written, or a deliberately growing file under attack.","commonSituations":"An external process appending to a .md file in the vault mid-scan; a memory document being rewritten by another agent while this reader has it open; a misconfigured tool treating a vault file as a log; filesystem behavior where the file was open in append mode elsewhere.","solutions":["Ensure memory files are written atomically (writeCreateOnly already does) and never appended to in place — find and stop whatever is appending.","Re-run the read after the concurrent writer has finished; the file will then be stable.","Quarantine the growing file (move it out of the vault) and re-save it as a fixed memory via saveMemory.","If the growth is legitimate, split the document so each file is bounded and immutable."],"exampleFix":"// before: another process appends to mem_x.md mid-scan, read aborts\n// stop the appender, then re-save as an immutable memory\nfs.renameSync(growingPath, growingPath + '.bak');\nsaveMemory({ title: '...fixed body...', body: fixedBody });\n// after: vault contains only immutable, size-bounded files","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"async function readStableSize(filePath, options, retries = 2) {\n  for (let i = 0; i <= retries; i++) {\n    try { return readRegularTextFile(filePath, options); }\n    catch (error) {\n      if (/too large \\(maximum/i.test(error.message) && i < retries) continue;\n      throw error;\n    }\n  }\n}","preventionTips":["Never append to vault files in place; always write a new memory with saveMemory.","Stop any external process that appends to .md files inside the vault.","Serialize vault reads/writes so a file cannot grow mid-read.","If a file is being actively appended, move it out of the vault and re-save as immutable."],"tags":["memory-vault","toctou","size-limits","concurrency","filesystem"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}