santifer/career-ops · error · Error

Could not parse existing candidates file at

Error message

Could not parse existing candidates file at ${candidatesPath}: ${e.message}

What it means

appendCandidate appends a reply-candidate entry to data/reply-candidates.json, an array file. If the existing file exists but is not valid JSON, it throws with the path and the underlying SyntaxError message rather than silently truncating the user's data.

Solutions

  1. Open the file at candidatesPath and fix the JSON syntax error reported in e.message
  2. Validate with `node -e "JSON.parse(require('fs').readFileSync('data/reply-candidates.json','utf8'))"` to locate the error
  3. If unrecoverable, back up the file and rebuild it as a valid JSON array of the entries you want to keep
  4. Re-run the paste-reply command after the file parses

Example fix

// before
appendCandidate(candidate); // throws on corrupt file
// after
try {
  appendCandidate(candidate);
} catch (e) {
  if (e.message.startsWith('Could not parse existing candidates file')) {
    console.error('Fix or restore data/reply-candidates.json first:', e.message);
  }
}
Defensive patterns

Strategy: validation

Validate before calling

function canParseJsonArray(p) { try { return Array.isArray(JSON.parse(readFileSync(p, 'utf-8'))); } catch { return false; } }

Try / catch

try { appendCandidate(c); } catch (e) { if (e.message.includes('Could not parse existing candidates file')) { backup(candidatesPath); console.error('Repair data/reply-candidates.json before appending'); } else throw e; }

Prevention

When it happens

Trigger: appendCandidate(candidate) called while data/reply-candidates.json contains malformed JSON — truncated write, hand-edited syntax error, concatenation of two runs, encoding corruption.

Common situations: A previous paste-reply run was killed mid-write; the user manually edited the JSON and left a trailing comma; a merge of two files produced invalid syntax; the file was written by another tool with non-JSON content.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16). Data as JSON: /api/errors/1b0a6e07aedf2061. Report an issue: GitHub.

Appendix: source

Thrown at paste-reply.mjs:122

    // Classification is reply-watch.mjs's job, not this script's — leaving
    // signal unset is safe (see file header comment for why).
    signal: null,
  };
}

/**
 * Append a candidate to the candidates JSON file, creating the file/array if
 * missing, without disturbing any existing entries. Exported for direct unit
 * testing. Returns the total candidate count after the append.
 */
export function appendCandidate(candidate, candidatesPath = CANDIDATES_PATH) {
  let candidates = [];
  if (fs.existsSync(candidatesPath)) {
    let parsed;
    try {
      parsed = JSON.parse(fs.readFileSync(candidatesPath, 'utf-8'));
    } catch (e) {
      throw new Error(`Could not parse existing candidates file at ${candidatesPath}: ${e.message}`);
    }
    if (!Array.isArray(parsed)) {
      throw new Error(`Existing candidates file at ${candidatesPath} is not a JSON array`);
    }
    candidates = parsed;
  } else {
    fs.mkdirSync(path.dirname(candidatesPath), { recursive: true });
  }
  candidates.push(candidate);
  // Write-then-rename so an interrupted write (crash, signal, disk full)
  // can never leave the real candidates file truncated/corrupted.
  const tmpPath = `${candidatesPath}.tmp`;
  fs.writeFileSync(tmpPath, JSON.stringify(candidates, null, 2), 'utf-8');
  renameSyncWithRetry(tmpPath, candidatesPath);
  return candidates.length;
}

// Collect subject/from/body from stdin via a single readline.Interface and a

View on GitHub (pinned to aac998c7ed)