usestrix/strix · error · RuntimeError

Cannot resume scan {scan_id}: agents.json has no root agent

Error message

Cannot resume scan {scan_id}: agents.json has no root agent (parent=None)

What it means

Raised on the resume path (strix/core/runner.py:219) after coordinator.restore(snap) succeeds but no agent in the restored parent_of map has parent None — i.e. the snapshot contains no root agent. Every Strix scan graph must have exactly one root agent (parent=None) to drive the run; a snapshot with only sub-agents is structurally invalid and resume is refused.

Source

Thrown at strix/core/runner.py:219

        await coordinator.restore(snap)
        report_state = get_global_report_state()
        if report_state is not None:
            budget_stopped, reserve_stopped = recomputed_budget_flags(
                report_state.get_total_llm_cost(),
                max_budget_usd,
                interactive=interactive,
            )
            await coordinator.reset_budget_stops(
                budget_stopped=budget_stopped,
                reserve_stopped=reserve_stopped,
                budget_paused=interactive and coordinator.budget_paused,
            )
        for aid, parent in coordinator.parent_of.items():
            if parent is None:
                root_id = aid
                break
        if root_id is None:
            raise RuntimeError(
                f"Cannot resume scan {scan_id}: agents.json has no root agent (parent=None)",
            )
        logger.info(
            "Resume: restored coordinator with %d agent(s); root=%s",
            len(coordinator.statuses),
            root_id,
        )
    else:
        root_id = uuid.uuid4().hex[:8]

    logger.info("Bringing up sandbox session for scan %s", scan_id)
    bundle = await session_manager.create_or_reuse(
        scan_id,
        image=image,
        local_sources=local_sources or [],
        extra_files=extra_files,
        status_sink=status_sink,
    )

View on GitHub (pinned to 8551339130)

Solutions

  1. Inspect agents.json and verify one entry has "parent": null; if absent, the snapshot is not a complete scan graph.
  2. Resume with the same Strix version that produced the run (pip/uv pin) so the snapshot schema matches.
  3. Otherwise start a new scan; notes/todos hydrated from the run dir still carry over context manually.

Example fix

# before
$ strix resume scan1   # agents.json has no root agent (parent=None)

# after
$ python -c "import json;s=json.load(open('strix_runs/scan1/agents.json'));print([k for k,v in s.get('parent_of',{}).items() if v is None])"
# [] -> snapshot is incomplete; start a fresh scan instead
Defensive patterns

Strategy: validation

Validate before calling

import json, pathlib
snap = json.loads((pathlib.Path(run_dir) / 'agents.json').read_text())
has_root = any(p is None for p in snap.get('parent_of', {}).values())
if not has_root:
    print('snapshot has no root agent; cannot resume — start a fresh scan')

Type guard

def snapshot_has_root(run_dir: str) -> bool:
    import json, pathlib
    s = json.loads((pathlib.Path(run_dir) / 'agents.json').read_text())
    return any(p is None for p in s.get('parent_of', {}).values())

Try / catch

try:
    await run_strix_scan(..., is_resume=True)
except RuntimeError as exc:
    if 'no root agent' in str(exc):
        start_fresh_scan_with_notes_from(run_dir)  # manual context carry-over
    else:
        raise

Prevention

When it happens

Trigger: Resuming from a hand-edited agents.json where the root entry was removed; a snapshot written by an older/different schema that serializes parentage differently (all agents report a parent); corrupted-but-parseable JSON that dropped the root record.

Common situations: Manual surgery on run artifacts; version skew between the Strix that wrote the snapshot and the one resuming; snapshots from aborted first-runs that never spawned the root correctly.

Related errors


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/b26fdb769fe94766. Report an issue: GitHub.