{"record":{"id":"8f3a747392f3a436","repo":"usestrix/strix","slug":"cannot-resume-scan-scan-id-missing-sdk-session","errorCode":null,"errorMessage":"Cannot resume scan {scan_id}: missing SDK session database at {agents_db}","messagePattern":"Cannot resume scan (.+?): missing SDK session database at (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"strix/core/runner.py","lineNumber":198,"sourceCode":"        coordinator = AgentCoordinator()\n    coordinator.set_snapshot_path(agents_path)\n\n    from strix.tools.notes.tools import hydrate_notes_from_disk\n    from strix.tools.todo.tools import hydrate_todos_from_disk\n\n    hydrate_todos_from_disk(state_dir)\n    hydrate_notes_from_disk(state_dir)\n\n    root_id: str | None = None\n    if is_resume:\n        try:\n            snap = json.loads(agents_path.read_text(encoding=\"utf-8\"))\n        except (OSError, json.JSONDecodeError) as exc:\n            raise RuntimeError(\n                f\"Cannot resume scan {scan_id}: agents.json is unreadable: {exc}\",\n            ) from exc\n        if not agents_db.exists():\n            raise RuntimeError(\n                f\"Cannot resume scan {scan_id}: missing SDK session database at {agents_db}\",\n            )\n        await coordinator.restore(snap)\n        report_state = get_global_report_state()\n        if report_state is not None:\n            budget_stopped, reserve_stopped = recomputed_budget_flags(\n                report_state.get_total_llm_cost(),\n                max_budget_usd,\n                interactive=interactive,\n            )\n            await coordinator.reset_budget_stops(\n                budget_stopped=budget_stopped,\n                reserve_stopped=reserve_stopped,\n                budget_paused=interactive and coordinator.budget_paused,\n            )\n        for aid, parent in coordinator.parent_of.items():\n            if parent is None:\n                root_id = aid","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/core/runner.py#L180-L216","documentation":"Raised on the resume path (strix/core/runner.py:198) when agents.json parses fine but the SDK session database file (agents_db, e.g. the OpenAI Agents SDK sqlite session store inside the run directory) is missing. The snapshot alone is not enough: the SDK database holds per-agent conversation history, so without it the restored graph would have amnesia and resume is refused.","triggerScenarios":"Resuming a scan whose run directory was partially copied or cleaned (agents.json kept, session db deleted); the scan was made by an older Strix version that did not create the db; file was excluded by a backup/glob filter.","commonSituations":"Copying run dirs between machines with rsync exclude patterns; cleanup scripts that remove *.db*; downgrading or jumping across Strix versions where the session-db layout changed.","solutions":["Check that the file at the printed agents_db path exists in the original run directory and copy the whole run dir intact (including the db) before resuming.","If the db is gone for good, start a new scan; the readable artifacts (report, notes, findings) from the old run remain usable.","Re-run the previous scan with the same Strix version that created it if the mismatch came from an upgrade."],"exampleFix":"# before\nrsync -av --exclude='*.db' old-host:strix_runs/scan1 ./   # db dropped\nstrix resume scan1                                             # missing SDK session database\n\n# after\nrsync -av old-host:strix_runs/scan1 ./strix_runs/scan1          # copy everything\nstrix resume scan1","handlingStrategy":"validation","validationCode":"import pathlib\nrun = pathlib.Path(run_dir)\nok = (run / 'agents.json').exists() and agents_db_path(run).exists()\nif not ok:\n    print('run dir incomplete: copy the ENTIRE run directory before resuming')","typeGuard":"def run_dir_is_complete(run_dir: str, agents_db: str) -> bool:\n    import pathlib\n    r = pathlib.Path(run_dir)\n    return (r / 'agents.json').is_file() and pathlib.Path(agents_db).exists()","tryCatchPattern":"try:\n    await run_strix_scan(..., is_resume=True)\nexcept RuntimeError as exc:\n    if 'missing SDK session database' in str(exc):\n        shutil.copytree(original_run_dir, run_dir, dirs_exist_ok=True)  # restore db\n        await run_strix_scan(..., is_resume=True)\n    else:\n        raise","preventionTips":["Copy run directories whole (no --exclude filters) when moving machines.","Pin the Strix version that created a run when resuming it."],"tags":["resume","session","database","filesystem"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}