jackwener/OpenCLI · error · CommandExecutionError
Invalid JSONL record in ${filePath} at line ${index + 1}: ${
Error message
Invalid JSONL record in ${filePath} at line ${index + 1}: ${error instanceof Error ? error.message : String(error)} What it means
loadJsonlArchiveState reads a JSONL file line by line; each record must parse and contain a valid, non-duplicate id. Any per-line failure (JSON syntax error, missing id, duplicate id) is rethrown as a CommandExecutionError naming the file, the 1-based line number, and the underlying cause. This pinpoints exactly which archive line is corrupt so resume state can be repaired.
Source
Thrown at clis/twitter/archive.js:55
if (!filePath || !fs.existsSync(filePath))
return { seen, count };
const text = fs.readFileSync(filePath, 'utf8');
for (const [index, line] of text.split('\n').entries()) {
const trimmed = line.trim();
if (!trimmed)
continue;
try {
const row = JSON.parse(trimmed);
if (!row?.id)
throw new Error('missing id');
const id = String(row.id);
if (seen.has(id))
throw new Error(`duplicate id ${id}`);
seen.add(id);
count += 1;
}
catch (error) {
throw new CommandExecutionError(`Invalid JSONL record in ${filePath} at line ${index + 1}: ${error instanceof Error ? error.message : String(error)}`);
}
}
return { seen, count };
}
export function appendJsonlRows(filePath, rows) {
if (!filePath || !Array.isArray(rows) || rows.length === 0)
return;
ensureParentDir(filePath);
// Escape LS/PS so JSONL stays one physical line even when tweet text contains them.
const text = rows
.map((row) => JSON.stringify(row).replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029'))
.join('\n') + '\n';
fs.appendFileSync(filePath, text, 'utf8');
}
export function removeResumeFile(filePath) {
removeFile(filePath);View on GitHub (pinned to 49907e53dc)
Solutions
- Open the file at the reported line number and fix or delete the malformed record
- If the last line is truncated (killed process), remove just that partial line — earlier records remain valid
- Deduplicate repeated id lines or restore the file from a backup
- If untrusted, delete the state file and rerun so a fresh archive is written
Example fix
// before (corrupt line 3)
{"id":"12"}
{"id":"13"
// after (truncated line removed)
{"id":"12"}
{"id":"13"} Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'node:fs';
function validateJsonl(filePath) {
const seen = new Set();
readFileSync(filePath, 'utf8').split('\n').forEach((line, i) => {
if (!line.trim()) return;
const rec = JSON.parse(line); // throws with line info on corrupt data
if (seen.has(rec.id)) throw new Error(`duplicate id ${rec.id} at line ${i + 1}`);
seen.add(rec.id);
});
} Type guard
function isValidRecord(rec) { return rec !== null && typeof rec === 'object' && typeof rec.id === 'string' && rec.id.length > 0; } Try / catch
try {
const state = await loadJsonlArchiveState(filePath);
} catch (err) {
const m = /line (\d+)/.exec(err.message);
if (m) console.error(`Fix or delete line ${m[1]} of ${filePath}, then rerun`);
else throw err;
} Prevention
- Don't hand-edit JSONL state files; if needed, validate after each edit
- Remove truncated trailing lines after a killed run
- Back up state files before manual repair
- Deduplicate ids when merging archives
When it happens
Trigger: The resume/state JSONL file contains a line that fails JSON.parse, lacks an id field, or repeats an id already seen — thrown from the state or jsonlState commands.
Common situations: Manually editing the JSONL file and breaking syntax, a previous run being killed mid-write leaving a truncated last line, file corruption from disk issues, or concatenating two archive files producing duplicate ids.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- archive search returned malformed JSON: ${error?.message ||
- archive wayback returned malformed JSON: ${error?.message ||
- coingecko returned malformed JSON: ${error?.message || error
- COMMAND_EXEC
- ${label} returned malformed JSON: ${err?.message ?? err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/1892fd511576f3b8.
Report an issue: GitHub.