usestrix/strix · error · BudgetExceededError
scan budget reached
Error message
scan budget reached
What it means
BudgetExceededError('scan budget reached') raised in `_run_agent` after the first input cycle when `coordinator.budget_stopped` is set: total LLM spend across the scan reached `max_budget_usd`. The agent is marked 'stopped' and the error propagates to terminate the run. (In interactive mode the hook instead raises BudgetPausedError which is suppressed here; this raise fires for the non-interactive/headless path or when the coordinator already recorded a stop.)
Source
Thrown at strix/core/execution.py:202
event_sink: StreamEventSink | None = None,
hooks: RunHooks[dict[str, Any]] | None = None,
) -> RunResultBase | None:
await coordinator.attach_runtime(
agent_id,
session=session,
interrupt_on_message=interactive,
)
result: RunResultBase | None = None
first_cycle_input = await _seed_and_prepare_first_input(
session, initial_input, start_parked=start_parked
)
budget_stopped = coordinator.budget_stopped
reserve_stopped = coordinator.reserve_stopped
if budget_stopped:
await coordinator.set_status(agent_id, "stopped")
raise BudgetExceededError("scan budget reached")
if reserve_stopped and context.get("parent_id") is not None:
await coordinator.set_status(agent_id, "stopped")
raise SubagentBudgetReservedError("scan reached the sub-agent budget reserve")
if reserve_stopped and start_parked and interactive and context.get("parent_id") is None:
await coordinator.send(agent_id, _reserve_notice())
if not (start_parked and interactive):
with contextlib.suppress(BudgetPausedError):
result = await _run_until_lifecycle(
agent,
coordinator,
agent_id,
initial_input=first_cycle_input,
run_config=run_config,
context=context,
max_turns=max_turns,
session=session,View on GitHub (pinned to 8551339130)
Solutions
- Re-run with a higher budget: `strix -n -t ./ --max-budget 50`
- Use `--scan-mode quick` or narrow the target to reduce cost
- For interactive runs, the budget pauses instead of stopping — continue from the TUI after reviewing spend, or use extend_budget semantics
- Review the run artifacts (run.json llm_usage.cost) to see where cost went before re-running
Example fix
# before strix -n -t ./ --scan-mode deep --max-budget 5 # BudgetExceededError: scan budget reached # after strix -n -t ./ --scan-mode deep --max-budget 25
Defensive patterns
Strategy: validation
Validate before calling
# size the budget before launching: quick scans of small targets need ~1-5 USD, deep scans often 10-50+
import subprocess, json
def budget_from_previous_run(runs_dir: str, fallback: float = 10.0) -> float:
# read the last run.json cost and add headroom
try:
run = sorted(Path(runs_dir).glob("*/run.json"))[-1]
cost = json.loads(run.read_text())["llm_usage"]["cost"]
return max(fallback, cost * 1.5)
except (OSError, KeyError, IndexError):
return fallback Try / catch
from strix.core.exceptions import BudgetExceededError # module path per repo layout
try:
run_scan(target="./", scan_mode="quick", max_budget=10)
except BudgetExceededError as e:
# partial artifacts still written — inspect before re-running with a larger budget
... Prevention
- Start with quick mode to calibrate cost, then size --max-budget from run.json before deep runs
- Route sub-agents to cheaper models so the same budget buys more coverage
- In CI, exit-code 2 + run.json cost tells you whether to raise budget or shrink scope — automate that decision
When it happens
Trigger: A headless scan (`strix -n`) with `--max-budget N` where cumulative LLM cost recorded in report_state crosses N during the run; the coordinator's budget_stopped flag is observed after seeding the first input.
Common situations: Deep scan modes on large targets exhausting the budget; long autonomous runs where cost accumulates faster than expected; budget set too low relative to target size (e.g. --max-budget 1 on a deep scan).
Related errors
- scan reached the sub-agent budget reserve
- Sub-agent budget reserve reached: spent ${cost:.4f} of ${sel
AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15).
Data as JSON: /api/errors/080ef375eb926fed.
Report an issue: GitHub.