{"record":{"id":"4c27e952583c973a","repo":"affaan-m/ECC","slug":"cannot-read-coordination-json","errorCode":null,"errorMessage":"Cannot read coordination JSON.","messagePattern":"Cannot read coordination JSON\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/coordination-inventory.js","lineNumber":236,"sourceCode":"  } 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;\n      for (const name of ['STATUS.md', 'status.md']) {\n        try {\n          const data = readBounded(path.join(directory, entry.name, name), 65536);\n          const parsed = parseWorkerStatus(data.content);\n          let heartbeatAt = null;\n          try { if (parsed.updated) heartbeatAt = timestamp(parsed.updated); } catch { /* Unknown timestamp, not a heartbeat. */ }\n          tasks.push(normalizeTask({ id: entry.name, paths: [], status: parsed.state || 'unknown', heartbeatAt, statusFileModifiedAt: data.modifiedAt }));\n          loaded = true; break;\n        } catch { /* Try legacy lowercase status filename; report unreadable below. */ }\n      }","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/coordination-inventory.js#L218-L254","documentation":"readJson wraps readBounded + JSON.parse and deliberately collapses every failure other than the size-limit error into the generic message 'Cannot read coordination JSON.' It is thrown when the file is missing/unopenable, unreadable, or its contents are not valid JSON. The original cause is swallowed by design so callers get a stable error string, at the cost of hiding the root cause.","triggerScenarios":"Calling readJson(file) when: (1) the path does not exist (ENOENT); (2) permission is denied on the file or a parent directory; (3) the file content is malformed/truncated JSON so JSON.parse throws; (4) readBounded fails for any reason other than the size limit (e.g. open errors on special files).","commonSituations":"Running the coordination inventory before any agent has created the coordination state file, pointing the script at the wrong directory (stale config/path), a partially-written JSON file from a crashed process, or a hand-edited JSON file with a syntax error.","solutions":["Confirm the coordination JSON path exists and is spelled correctly: run ls -l on the configured directory/file before invoking the tool.","Validate the JSON manually (node -e \"JSON.parse(require('fs').readFileSync(path,'utf8'))\") to see the real parse error, since readJson masks it.","If the file is corrupt or truncated, delete it and let the tooling regenerate it, or restore it from a known-good backup.","Check file permissions (read access for the current user); fix with chmod/chown if a different user created the file."],"exampleFix":"// before: opaque failure\nconst manifest = readJson(statePath);\n\n// after: surface the underlying cause\ncatch (error) {\n  if (!fs.existsSync(statePath)) throw new Error(`Missing coordination state file: ${statePath}`);\n  console.error(error); // log real cause\n  throw error;\n}","handlingStrategy":"try-catch","validationCode":"if (!fs.existsSync(file)) throw new Error(`Coordination state file not found: ${file}`);\nconst raw = fs.readFileSync(file, 'utf8');\nJSON.parse(raw); // fail early with the real parse error","typeGuard":"function isParsableObject(text) { try { const v = JSON.parse(text); return v !== null && typeof v === 'object' && !Array.isArray(v); } catch { return false; } }","tryCatchPattern":"let manifest;\ntry {\n  manifest = readJson(file);\n} catch (error) {\n  if (error.message === 'Cannot read coordination JSON.') {\n    // fall back to a default/empty manifest after verifying the file is absent or corrupt\n    manifest = defaultManifest();\n  } else throw error;\n}","preventionTips":["Validate JSON files with a linter/parser after any manual edit.","Write JSON atomically (write temp file + rename) so readers never see truncated content.","Check file existence before invoking readJson in scripts.","Log the underlying error (readJson swallows the cause) when debugging."],"tags":["json","filesystem","error-masking","nodejs"],"backgroundTag":"json-parse-error","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"}