{"record":{"id":"231b45e70335509f","repo":"usestrix/strix","slug":"scan-reached-the-sub-agent-budget-reserve","errorCode":null,"errorMessage":"scan reached the sub-agent budget reserve","messagePattern":"scan reached the sub-agent budget reserve","errorType":"exception","errorClass":"SubagentBudgetReservedError","httpStatus":null,"severity":"warning","filePath":"strix/core/execution.py","lineNumber":205,"sourceCode":"    await coordinator.attach_runtime(\n        agent_id,\n        session=session,\n        interrupt_on_message=interactive,\n    )\n    result: RunResultBase | None = None\n\n    first_cycle_input = await _seed_and_prepare_first_input(\n        session, initial_input, start_parked=start_parked\n    )\n\n    budget_stopped = coordinator.budget_stopped\n    reserve_stopped = coordinator.reserve_stopped\n    if budget_stopped:\n        await coordinator.set_status(agent_id, \"stopped\")\n        raise BudgetExceededError(\"scan budget reached\")\n    if reserve_stopped and context.get(\"parent_id\") is not None:\n        await coordinator.set_status(agent_id, \"stopped\")\n        raise SubagentBudgetReservedError(\"scan reached the sub-agent budget reserve\")\n\n    if reserve_stopped and start_parked and interactive and context.get(\"parent_id\") is None:\n        await coordinator.send(agent_id, _reserve_notice())\n\n    if not (start_parked and interactive):\n        with contextlib.suppress(BudgetPausedError):\n            result = await _run_until_lifecycle(\n                agent,\n                coordinator,\n                agent_id,\n                initial_input=first_cycle_input,\n                run_config=run_config,\n                context=context,\n                max_turns=max_turns,\n                session=session,\n                interactive=interactive,\n                event_sink=event_sink,\n                hooks=hooks,","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/core/execution.py#L187-L223","documentation":"SubagentBudgetReservedError raised when a child agent (context.parent_id is not None) is halted because total spend reached the sub-agent reserve threshold (a fraction of max_budget_usd, _SUBAGENT_BUDGET_RESERVE). The reserve exists so children can't consume the whole budget and starve the root agent, which needs headroom to finish and write the report. The child is marked 'stopped' and the error terminates that child's run.","triggerScenarios":"Non-interactive scans with sub-agents: cost crosses `max_budget_usd * _SUBAGENT_BUDGET_RESERVE` while a spawned agent is running; the child observes coordinator.reserve_stopped at the first-cycle checkpoint and raises.","commonSituations":"Sub-agent-heavy scans (deep mode spawning many specialists) where children burn budget early; budget set tight so the reserve line is crossed quickly; an expensive model configured for sub-agents.","solutions":["Increase --max-budget so the reserve threshold leaves children enough room","Configure cheaper models for sub-agents (model routing config) to slow cost growth","Reduce scan breadth (quick mode, fewer sub-agents) so the root finishes within the reserve","Treat as partial: the root agent may still complete the scan with what it has; check the report before re-running"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# keep sub-agent model cost low so children stay under the reserve line\nSUBAGENT_MODEL = \"openai/gpt-4o-mini\"        # cheap\nROOT_MODEL = \"openai/gpt-5.4\"               # strong\n# budget must cover children up to reserve AND the root's finish\nassert max_budget > expected_child_spend / _SUBAGENT_BUDGET_RESERVE","typeGuard":null,"tryCatchPattern":"from strix.core.exceptions import SubagentBudgetReservedError\n\ntry:\n    await run_child_agent(...)\nexcept SubagentBudgetReservedError:\n    # designed stop, not a crash: parent still has reserve to finish\n    log(\"child stopped at reserve; root continues\")","preventionTips":["Budget so that max_budget * reserve fraction exceeds expected total child spend","Cap the number of concurrent sub-agents in scan config","Catch SubagentBudgetReservedError where children are spawned and treat it as a normal completion signal"],"tags":["budget","subagent","cost-control","scan"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}