{"record":{"id":"e66c4185dd644fd1","repo":"abi/screenshot-to-code","slug":"generation-stopped-this-variant-exceeded-its-reso","errorCode":null,"errorMessage":"Generation stopped: this variant exceeded its resource limit.","messagePattern":"Generation stopped: this variant exceeded its resource limit\\.","errorType":"exception","errorClass":"BudgetExceededError","httpStatus":null,"severity":"error","filePath":"backend/agent/engine.py","lineNumber":276,"sourceCode":"                        started_tool_ids,\n                        streamed_lengths,\n                    )\n\n            turn = await session.stream_turn(on_event)\n\n            if not turn.tool_calls:\n                return await self._finalize_response(turn.assistant_text)\n\n            # Abort only when the run would otherwise continue: a run that\n            # just produced its final answer is already paid for. Unpriced\n            # models return None and are not bounded.\n            spent = session.total_cost_usd()\n            if spent is not None and spent > GENERATION_MAX_COST_USD:\n                print(\n                    f\"[BUDGET] Aborting variant {self.variant_index}: \"\n                    f\"${spent:.2f} > ${GENERATION_MAX_COST_USD:.2f}\"\n                )\n                raise BudgetExceededError()\n\n            executed_tool_calls: List[ExecutedToolCall] = []\n            for tool_call in turn.tool_calls:\n                tool_event_id = tool_call.id or self._next_event_id(\"tool\")\n                if tool_event_id not in started_tool_ids:\n                    await self._send(\n                        \"toolStart\",\n                        data={\n                            \"name\": tool_call.name,\n                            \"input\": summarize_tool_input(tool_call, self.file_state),\n                        },\n                        event_id=tool_event_id,\n                    )\n\n                if tool_call.name == \"create_file\":\n                    content = extract_content_from_args(tool_call.arguments)\n                    if content:\n                        await self._stream_code_preview(tool_event_id, content)","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/abi/screenshot-to-code/blob/d026163f586dfa8c5c10d28c36edd59a9d3b0e88/backend/agent/engine.py#L258-L294","documentation":"BudgetExceededError is raised by the agent engine's tool loop when the accumulated session cost (session.total_cost_usd()) exceeds GENERATION_MAX_COST_USD from backend config. It is checked only when the run would otherwise continue (tool calls pending), so a final answer is never aborted mid-stream; unpriced models return None and are never bounded. The frontend renders it as 'Generation stopped: this variant exceeded its resource limit.'","triggerScenarios":"A long multi-turn agent run (up to 30 tool-loop steps) whose cumulative token cost crosses the configured GENERATION_MAX_COST_USD cap before producing a final assistant answer without tool calls.","commonSituations":"GENERATION_MAX_COST_USD set very low for the model being used, expensive models (e.g. high-tier Claude/GPT) doing many image-generation tool calls, or a task that genuinely needs more turns than the budget allows.","solutions":["Raise GENERATION_MAX_COST_USD in backend/.env or config if the workload legitimately costs more.","Switch to a cheaper model or reduce the number of variants running concurrently (cost is per-variant).","Inspect the [BUDGET] console log line to see actual spend vs cap before changing anything.","If the run should degrade gracefully, catch BudgetExceededError in the caller and return the best partial assistant_text seen so far."],"exampleFix":"# before\nGENERATION_MAX_COST_USD=1.0\n\n# after (backend/.env)\nGENERATION_MAX_COST_USD=5.0","handlingStrategy":"validation","validationCode":"from backend.config import GENERATION_MAX_COST_USD\n# before starting an expensive variant, estimate feasibility\nif session.total_cost_usd() is not None and session.total_cost_usd() >= GENERATION_MAX_COST_USD:\n    raise BudgetExceededError()","typeGuard":null,"tryCatchPattern":"try:\n    result = await engine.run(model, messages)\nexcept BudgetExceededError:\n    # surface a friendly message, keep partial output if any\n    await send(\"status\", data={\"message\": \"Budget exceeded for this variant\"})","preventionTips":["Size GENERATION_MAX_COST_USD to model pricing x expected turns before starting a batch.","Watch for [BUDGET] console lines during long runs and adjust or abort early.","Prefer cheaper models for exploratory variants; reserve expensive ones for finals."],"tags":["budget","cost-limit","agent","config"],"backgroundTag":null,"analyzedSha":"d026163f586dfa8c5c10d28c36edd59a9d3b0e88","analyzedAt":"2026-08-14T22:02:06.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}