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

  1. Verify the file exists first: (STORE / f"{run_id}.journal.jsonl").exists()
  2. Ensure STORE resolves to the same absolute path across processes/environments
  3. 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

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


AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14). Data as JSON: /api/errors/5b0454893a8f140c. Report an issue: GitHub.