calesthio/OpenMontage · warning · ApprovalRequiredError

First paid use of tool {entry['tool']!r} requires approval

Error message

First paid use of tool {entry['tool']!r} requires approval

What it means

ApprovalRequiredError raised by CostTracker.reserve when require_approval_for_new_paid_tool is enabled, the entry has estimated_usd > 0, and the tool name is not in _approved_tools. It enforces an explicit opt-in the first time any paid tool is used, independent of amount. Once approve_tool(tool) is called the name is persisted in approved_tools and later reserves succeed.

Source

Thrown at tools/cost_tracker.py:138

        Raises BudgetExceededError in cap mode, or ApprovalRequiredError
        when the action exceeds the single-action approval threshold.
        """
        entry = self._find(entry_id)
        estimated = entry["estimated_usd"]

        # Check single-action approval threshold
        if estimated > self.single_action_approval_usd:
            if self.mode != BudgetMode.OBSERVE:
                raise ApprovalRequiredError(
                    f"Action costs ${estimated:.2f}, exceeds "
                    f"single-action threshold ${self.single_action_approval_usd:.2f}"
                )

        # Check new paid tool approval
        if self.require_approval_for_new_paid_tool and estimated > 0:
            if entry["tool"] not in self._approved_tools:
                if self.mode != BudgetMode.OBSERVE:
                    raise ApprovalRequiredError(
                        f"First paid use of tool {entry['tool']!r} requires approval"
                    )

        # Check budget
        if estimated > self.usable_budget_usd:
            message = (
                f"Reservation of ${estimated:.2f} exceeds usable budget "
                f"${self.usable_budget_usd:.2f}"
            )
            if self.mode == BudgetMode.CAP:
                raise BudgetExceededError(message)
            if self.mode == BudgetMode.WARN:
                entry["budget_warning"] = True
                entry["budget_warning_message"] = message

        entry["status"] = EntryStatus.RESERVED.value
        entry["reserved_usd"] = estimated
        entry["timestamp"] = self._now()

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Approve the tool once via tracker.approve_tool(entry['tool']) (it persists to the cost log) and retry reserve().
  2. Pre-populate approved_tools in the budget/cost-log config for tools you know are sanctioned.
  3. Disable require_approval_for_new_paid_tool if per-tool gating is not wanted.
  4. Run in OBSERVE mode for exploratory sessions where approvals should not block.

Example fix

# before
tracker.reserve(entry_id)  # first paid use of 'kling_tts' -> ApprovalRequiredError

# after
if entry["tool"] not in tracker._approved_tools:
    tracker.approve_tool(entry["tool"])
tracker.reserve(entry_id)
Defensive patterns

Strategy: validation

Validate before calling

def tool_approved(tracker, tool: str) -> bool:
    return tool in tracker._approved_tools

Try / catch

from tools.cost_tracker import ApprovalRequiredError

try:
    tracker.reserve(entry_id)
except ApprovalRequiredError as e:
    if "requires approval" in str(e):
        tracker.approve_tool(tool_name)
        tracker.reserve(entry_id)

Prevention

When it happens

Trigger: reserve() on the first paid entry for a tool with require_approval_for_new_paid_tool=True and mode != OBSERVE. Every new provider/tool (new image model, new TTS engine) triggers it once until approved.

Common situations: Fresh projects or fresh cost logs where approved_tools is empty; adding a new tool to a workflow after initial setup; loading an old cost log that predates the tool.

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/690ccc2abd8f817b. Report an issue: GitHub.