shareAI-lab/learn-claude-code · error · WorkflowInputError
resume journal not found for {run_id}
Error message
resume journal not found for {run_id} What it means
WorkflowJournal(resume=True) requires an existing <store>/<runId>.journal.jsonl to replay cached agent() results from. If the file does not exist, WorkflowInputError is raised — you cannot resume a run that never started or whose store was lost. The check happens before the journal is opened, so nothing is created or truncated on failure.
Source
Thrown at s16_workflow_runtime/code.py:333
RUNNER_FACTORY = MockAgentRunner
# -- Journal --
class WorkflowJournal:
"""Append-only <runId>.journal.jsonl. On resume, agent() calls whose
semantic key is already present are replayed from cache instead of re-run."""
def __init__(self, run_id, resume, store=None):
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
View on GitHub (pinned to 985456f4ad)
Solutions
- Verify the file exists first: (STORE / f"{run_id}.journal.jsonl").exists()
- Ensure STORE resolves to the same absolute path across processes/environments
- If the journal is gone, start a fresh run with reserve_run_id instead of resuming
Example fix
# before
result = resume(workflow, run_id=saved_id) # journal deleted
# after
if (STORE / f"{saved_id}.journal.jsonl").exists():
result = resume(workflow, run_id=saved_id)
else:
result = run(workflow, run_id=reserve_run_id(meta)) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def journal_exists(store: Path, run_id: str) -> bool:
return (store / f"{run_id}.journal.jsonl").exists()
if not journal_exists(STORE, run_id):
run_id = reserve_run_id(meta) # fall back to a fresh run
result = resume(workflow, run_id=run_id) Type guard
def is_resumable(store: Path, run_id: str) -> bool:
return (store / f"{run_id}.journal.jsonl").is_file() Try / catch
try:
result = resume(workflow, run_id=run_id)
except WorkflowInputError as exc:
if "resume journal not found" in str(exc):
result = run(workflow, run_id=reserve_run_id(meta))
else:
raise Prevention
- Pin STORE to one absolute path across environments
- Check existence before resume()
- Exclude *.journal.jsonl from cleanup/pruning jobs
When it happens
Trigger: resume(run_id) with a typo'd or hand-edited id. Resuming after the store directory was deleted, moved, or STORE was redefined (different path between runs). Resuming a run that crashed before its first journal write (the file is created on open, but a run reserved then aborted may only have <runId>.json).
Common situations: Store path configured per environment (local vs CI vs container volume) so the journal lives elsewhere. Cleanup jobs pruning 'old' .jsonl files. Run ids persisted in a DB but the file store is ephemeral.
Related errors
- invalid resume journal record at line {line_number}
- cached agent output failed schema validation: {err}
- could not allocate a unique workflow runId
- resume runId does not match workflow meta
- resume args do not match the original run
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/5b0454893a8f140c.
Report an issue: GitHub.