shareAI-lab/learn-claude-code · error · WorkflowInputError
token budget exceeded
Error message
token budget exceeded
What it means
ExecutionState.agent() checks Budget.remaining() before spawning each subagent and raises WorkflowInputError('token budget exceeded') when the run-wide token budget is already exhausted. The budget is shared across the whole workflow, including nested child workflows and parallel/pipeline agents, and only successful runs add their tokens via budget.add(). This is a hard stop so a workflow cannot silently overspend.
Source
Thrown at s16_workflow_runtime/code.py:461
def phase(self, title):
"""Start a phase; subsequent agent()s group under it. Upsert: emitting the
same phase again (e.g. from each pipeline item) does not re-announce it."""
self._phase = title
if title not in self._phases_seen:
self._phases_seen.add(title)
self.task.progress_event("workflow_phase", title=title)
def log(self, message):
"""Emit a workflow_log progress line."""
self.task.progress_event("workflow_log", message=message)
async def agent(self, prompt, schema=None, label=None, phase=None):
"""Spawn one subagent. With a schema, force StructuredOutput + validate
(retry once). On resume, a cached key short-circuits the run."""
label = label or (prompt[:24] + "...")
self._limits.claim_agent()
if self.budget.remaining() <= 0:
raise WorkflowInputError("token budget exceeded")
key = self.journal.key("agent", label, prompt, schema)
cached = self.journal.cached(key)
if cached is not MISS:
if schema is not None:
ok, err = SimpleJsonSchema(schema).validate(cached)
if not ok:
raise WorkflowInputError(
f"cached agent output failed schema validation: {err}"
)
self.task.progress_event("workflow_agent", label=label,
phase=phase or self._phase, status="cached")
return cached
async with self._limits.semaphore:
run = await asyncio.to_thread(
self.runner.run, prompt, schema, label
)View on GitHub (pinned to 985456f4ad)
Solutions
- Raise the token budget total configured for the workflow (e.g. meta's budget field) so remaining() stays positive for all planned agent() calls.
- Reduce agent count: batch items, shrink pipeline dimensions, or reuse one agent call for multiple inputs.
- Shrink prompts/outputs: tighten the JSON schema (fewer/lower max lengths) and trim the text embedded into prompts.
- If mid-run: fix the budget and resume from the last runId — cached agents replay without new token spend, but the budget total must be > 0 at each call site.
Example fix
// before
meta = {"name": "review", "tokenBudget": 5000}
// 20 pipeline agents x ~400 tokens each exhausts it
// after
meta = {"name": "review", "tokenBudget": 50000}
// or reduce fan-out:
for dimension in ["security", "correctness"]: # was 6 dimensions
... Defensive patterns
Strategy: validation
Validate before calling
async def agent_guarded(ctx, prompt, schema=None, label=None):
if ctx.budget.remaining() <= 0:
raise InsufficientBudget(f"remaining={ctx.budget.remaining()}")
return await ctx.agent(prompt, schema=schema, label=label) Type guard
def has_budget(ctx) -> bool:
return ctx.budget.remaining() > 0 Try / catch
from s16_workflow_runtime import WorkflowInputError
try:
out = await ctx.agent(prompt, schema=S)
except WorkflowInputError as e:
if "budget" in str(e):
checkpoint_and_report_budget(ctx) # surface spent/remaining, stop cleanly
raise Prevention
- Size the token budget from a dry-run: estimate tokens per agent x number of pipeline items x dimensions, then add 30% headroom.
- Log ctx.budget.spent()/remaining() in each phase so exhaustion is visible before it throws.
- Keep fan-out (pipeline breadth x dimensions) proportional to the budget; cap items per run.
When it happens
Trigger: Calling ctx.agent() (directly or inside pipeline/parallel stages) after prior agent runs have consumed >= the budget total configured for the workflow run. Note the check runs BEFORE the journal cache lookup, so even a resume that would only replay cached agents fails if the fresh Budget object is created with an already-exhausted total.
Common situations: Budget total in workflow meta set too low for the number of agent calls; a pipeline fan-out over many items multiplying token usage; resuming a large run with the same tight budget; a verbose schema causing big outputs.
Related errors
- token budget exceeded ({self._spent + n} > {self._total})
- agent() cap reached ({AGENT_CAP})
- could not allocate a unique workflow runId
- invalid workflow runId
- workflow run {run_id} is already active
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/c4bddd686571ee87.
Report an issue: GitHub.