{"record":{"id":"c3314f3fafee23c3","repo":"affaan-m/ECC","slug":"input-exceeds-file-limit","errorCode":null,"errorMessage":"Input exceeds file limit.","messagePattern":"Input exceeds file limit\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/coordination-inventory.js","lineNumber":226,"sourceCode":"    const result = (deps.execFileSync || execFileSync)('ps', ['-p', pids.join(','), '-o', 'pid=,ppid=,rss=,etime=,stat='],\n      { encoding: 'utf8', timeout: 2000, maxBuffer: 65536, shell: false, stdio: ['ignore','pipe','pipe'] });\n    const processes = String(result).split('\\n').filter(l => l.trim()).map(line => {\n      const match = line.trim().match(/^(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+([\\d:-]+)\\s+([A-Za-z+<>NsElLW]+)$/);\n      if (!match) throw new Error('Invalid process metadata.');\n      const values = match.slice(1,4).map(Number);\n      if (values.some(v => !Number.isSafeInteger(v)) || !pids.includes(values[0])) throw new Error('Invalid process metadata.');\n      return { pid: values[0], parentPid: values[1], rssBytes: values[2] * 1024, elapsed: match[4], flags: match[5] };\n    });\n    return { memory, processStatus: 'ok', processes };\n  } catch { return { memory, processStatus: 'unavailable', processes: [] }; }\n}\n\nfunction readBounded(file, limit = MAX_BYTES) {\n  // Refuse symlink final components, devices and files beyond the byte budget.\n  const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);\n  try {\n    const stat = fs.fstatSync(fd);\n    if (!stat.isFile() || stat.size > limit) throw new Error('Input exceeds file limit.');\n    const buffer = Buffer.alloc(limit + 1);\n    let size = 0; let count;\n    do { count = fs.readSync(fd, buffer, size, buffer.length - size, null); size += count; } while (count && size < buffer.length);\n    if (size > limit) throw new Error('Input exceeds file limit.');\n    return { content: buffer.subarray(0,size).toString('utf8'), modifiedAt: stat.mtime.toISOString() };\n  } finally { fs.closeSync(fd); }\n}\nfunction readJson(file) {\n  try { return JSON.parse(readBounded(file).content); }\n  catch (error) { throw new Error(error.message === 'Input exceeds file limit.' ? error.message : 'Cannot read coordination JSON.'); }\n}\nfunction collectTaskFiles(directory) {\n  try {\n    const entries = fs.readdirSync(directory, { withFileTypes: true }).filter(e => e.isDirectory() && !e.name.startsWith('.')).sort((a,b) => a.name < b.name ? -1 : 1);\n    if (entries.length > 64) throw new Error('Too many task directories.');\n    const tasks = []; const unreadable = [];\n    for (const entry of entries) {\n      let loaded = false;","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/coordination-inventory.js#L208-L244","documentation":"readBounded reads a file with a hard byte budget (default MAX_BYTES) to prevent memory exhaustion and symlink/device attacks. It throws 'Input exceeds file limit.' when the file's stat size exceeds the limit or the streamed read ends up larger than the budget.","triggerScenarios":"readJson/data reading a store or inventory file larger than MAX_BYTES; a corrupted/append-only store that grew unbounded; caller passing a tiny custom limit on a normal file; a device/FIFO-like file failing the isFile check path where size check trips first.","commonSituations":"Long-running project where coordination store accumulated thousands of items past the size cap; passing the wrong (small) limit argument; pointing the inventory at a large log file by config mistake.","solutions":["Check the file size (ls -lh) and compare against MAX_BYTES in coordination-inventory.js.","Prune/compact the store file — archive completed work items so the file fits the budget.","Pass a larger explicit limit argument to readBounded if the data legitimately needs it.","Verify config points at the intended store file, not an oversized log or dump."],"exampleFix":"// before\nconst data = readBounded(file); // default MAX_BYTES\n// after\nconst data = readBounded(file, 10 * 1024 * 1024); // 10MB budget\n// or prune the store until stat.size <= MAX_BYTES","handlingStrategy":"validation","validationCode":"const stat = fs.statSync(file);\nif (stat.size > MAX_BYTES) throw new Error(`${file} is ${stat.size}B, exceeds ${MAX_BYTES}B limit — prune or raise limit.`);","typeGuard":"function withinBudget(file, limit = MAX_BYTES) { try { return fs.statSync(file).size <= limit; } catch { return false; } }","tryCatchPattern":"try { const data = readBounded(file); } catch (e) {\n  if (e.message === 'Input exceeds file limit.') { pruneStore(file); return readBounded(file); }\n  throw e;\n}","preventionTips":["Monitor store file size; alert before it approaches MAX_BYTES.","Archive/prune completed work items routinely.","Never point the inventory at logs or dumps; keep paths explicit in config.","Raise the limit only deliberately, with the size growth understood."],"tags":["file-io","limits","safety"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}