shareAI-lab/learn-claude-code · error · WorkflowInputError
invalid resume journal record at line {line_number}
Error message
invalid resume journal record at line {line_number} What it means
On resume, every line of the journal must be a JSON object with a string 'key' and a 'value' field. The first line violating this — unparseable JSON, a non-dict, or a missing/mistyped key — raises WorkflowInputError with that 1-based line number (chained from the underlying JSONDecodeError/ValueError). The journal is append-only JSONL written by the runtime, so corruption is external.
Source
Thrown at s16_workflow_runtime/code.py:344
store = STORE if store is None else store
store.mkdir(parents=True, exist_ok=True)
self.path = store / f"{run_id}.journal.jsonl"
self.resume = resume
self.cache = {}
if resume:
if not self.path.exists():
raise WorkflowInputError(f"resume journal not found for {run_id}")
for line_number, line in enumerate(self.path.read_text().splitlines(), start=1):
try:
rec = json.loads(line)
if (
not isinstance(rec, dict)
or not isinstance(rec.get("key"), str)
or "value" not in rec
):
raise ValueError("expected key/value record")
except (json.JSONDecodeError, ValueError) as exc:
raise WorkflowInputError(
f"invalid resume journal record at line {line_number}"
) from exc
self.cache[rec["key"]] = rec["value"]
self._f = self.path.open("a")
else:
self._f = self.path.open("w") # fresh run truncates
def key(self, kind, label, prompt, schema):
# Deterministic semantic key, independent of concurrency order, so a
# parallel/pipeline call gets the same key on resume.
basis = f"{kind}|{label}|{prompt}|{json.dumps(schema, sort_keys=True)}"
return f"{kind}-{_stable_hash(basis) % 10**10:010d}"
def cached(self, key):
return self.cache.get(key, MISS)
def record(self, key, value):
self._f.write(json.dumps({"key": key, "value": value}) + "\n")View on GitHub (pinned to 985456f4ad)
Solutions
- Inspect the reported line: if it is a torn trailing line, delete that single line — earlier records still replay
- Restore the journal from backup if corruption is not just the tail
- If entries are unusable, start a fresh run rather than hand-editing records
Example fix
# before: journal ends with torn line
{"key": "agent-0001234567", "value": {"summary": "..."}}
{"key": "agent-000987654
# after: remove the incomplete trailing line
{"key": "agent-0001234567", "value": {"summary": "..."}} Defensive patterns
Strategy: validation
Validate before calling
import json
from pathlib import Path
def journal_is_intact(path: Path) -> bool:
for line in path.read_text().splitlines():
try:
rec = json.loads(line)
except json.JSONDecodeError:
return False
if not isinstance(rec, dict) or not isinstance(rec.get("key"), str) or "value" not in rec:
return False
return True
assert journal_is_intact(STORE / f"{run_id}.journal.jsonl") Try / catch
try:
result = resume(workflow, run_id=run_id)
except WorkflowInputError as exc:
if "invalid resume journal record at line" in str(exc):
line_no = int(str(exc).rsplit("line ", 1)[1].rstrip(")"))
path = STORE / f"{run_id}.journal.jsonl"
lines = path.read_text().splitlines()
# drop the corrupt (typically torn trailing) line and retry once
path.write_text("\n".join(lines[: line_no - 1]) + "\n")
result = resume(workflow, run_id=run_id)
else:
raise Prevention
- Never hand-edit journal files; treat them as opaque append-only logs
- Tolerate crashes by dropping only the final torn line, never middle lines
- Keep the store off editors/sync tools that rewrite files
When it happens
Trigger: A partially written last line after a crash mid-append (power loss, SIGKILL during write). Manual edits to the .jsonl file. Disk corruption or an editor that re-saved with different encoding/line endings merging records. Concurrent writers to the same journal without the run lock.
Common situations: Hard-killed processes leaving a torn final line. Developers hand-trimming journals to 'clean' bad entries. Sync tools (Dropbox-style) mangling concurrent writes.
Related errors
- resume journal not found for {run_id}
- cached agent output failed schema validation: {err}
- resume runId does not match workflow meta
- resume args do not match the original run
- resume snapshot not found for {run_id}
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/90d4637df744bc9a.
Report an issue: GitHub.