{"record":{"id":"1b0a6e07aedf2061","repo":"santifer/career-ops","slug":"could-not-parse-existing-candidates-file-at-cand","errorCode":null,"errorMessage":"Could not parse existing candidates file at ${candidatesPath}: ${e.message}","messagePattern":"Could not parse existing candidates file at (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"paste-reply.mjs","lineNumber":120,"sourceCode":"    // Classification is reply-watch.mjs's job, not this script's — leaving\n    // signal unset is safe (see file header comment for why).\n    signal: null,\n  };\n}\n\n/**\n * Append a candidate to the candidates JSON file, creating the file/array if\n * missing, without disturbing any existing entries. Exported for direct unit\n * testing. Returns the total candidate count after the append.\n */\nexport function appendCandidate(candidate, candidatesPath = CANDIDATES_PATH) {\n  let candidates = [];\n  if (fs.existsSync(candidatesPath)) {\n    let parsed;\n    try {\n      parsed = JSON.parse(fs.readFileSync(candidatesPath, 'utf-8'));\n    } catch (e) {\n      throw new Error(`Could not parse existing candidates file at ${candidatesPath}: ${e.message}`);\n    }\n    if (!Array.isArray(parsed)) {\n      throw new Error(`Existing candidates file at ${candidatesPath} is not a JSON array`);\n    }\n    candidates = parsed;\n  } else {\n    fs.mkdirSync(path.dirname(candidatesPath), { recursive: true });\n  }\n  candidates.push(candidate);\n  // Write-then-rename so an interrupted write (crash, signal, disk full)\n  // can never leave the real candidates file truncated/corrupted.\n  const tmpPath = `${candidatesPath}.tmp`;\n  fs.writeFileSync(tmpPath, JSON.stringify(candidates, null, 2), 'utf-8');\n  fs.renameSync(tmpPath, candidatesPath);\n  return candidates.length;\n}\n\n// Collect subject/from/body from stdin via a single readline.Interface and a","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/paste-reply.mjs#L102-L138","documentation":"Thrown by appendCandidate() in paste-reply.mjs when data/reply-candidates.json exists but JSON.parse fails on its contents. The function is an append-only writer using write-then-rename for crash safety; this guard stops it from appending onto a corrupted base file, which would propagate the corruption.","triggerScenarios":"The candidates file was partially written/truncated by a previous crash that bypassed the write-then-rename (e.g. an editor or external tool overwrote it directly); manual edit left invalid JSON; disk corruption; an encoding mismatch (BOM, CRLF mangled).","commonSituations":"A user hand-edited data/reply-candidates.json and broke the syntax; a sync tool (Dropbox/OneDrive) wrote a temp/conflict file over it; a previous version of the code wrote without the tmp+rename atomic pattern.","solutions":["Validate the file with a JSON linter to locate the syntax error, then fix or delete it.","If unrecoverable, back up the corrupt file, delete it, and let appendCandidate recreate a fresh empty array.","Avoid editing reply-candidates.json by hand — it is managed by paste-reply.mjs.","Run `node -e \"JSON.parse(require('fs').readFileSync('data/reply-candidates.json','utf8'))\"` to confirm the fix."],"exampleFix":"// before: file contains trailing comma -> throws on parse\n[\n  { ... },\n]\n// after: valid JSON\n[\n  { ... }\n]","handlingStrategy":"validation","validationCode":"import { readFileSync } from 'fs';\nfunction candidatesFileValid(p) {\n  try { return Array.isArray(JSON.parse(readFileSync(p, 'utf8'))); }\n  catch { return false; }\n}\nif (!candidatesFileValid(p)) {\n  // repair or back up + delete before calling appendCandidate\n}","typeGuard":"null","tryCatchPattern":"try {\n  appendCandidate(c);\n} catch (e) {\n  if (/Could not parse/.test(e.message)) {\n    // back up corrupt file, delete, retry\n  } else throw e;\n}","preventionTips":["Never hand-edit data/reply-candidates.json — let paste-reply.mjs own it.","Back up the file before any external sync tool touches it.","Run a JSON validity check as part of CI/pre-commit."],"tags":["json","file-corruption","paste-reply","data-integrity"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}