Skip to content

[bug]: opencode-zen — Console retired budgets/org (now 409); budgets moved to /api/policies/current-budgets #320

Open

Description

@jkemp814

Versions

  • opencode-quota 5.0.2 (npm latest and next; no newer version exists)
  • OpenCode v2, Linux (Fedora Silverblue)

Symptom

The opencode-zen provider shows no monthly limit and logs an error, even though a workspace budget is configured in the Console:

opencode_zen:
- console_auth_state: configured
- balance_usd: USD 27.75806885
- monthly_limit_usd: (none)
- monthly_usage_usd: USD 11.4977624
- budget_source: credit_limit
- live_fetch_error: OpenCode Console budgets/org error 409
- live_probe: partial

Other providers (e.g. github-copilot) track correctly, so this is provider-specific, not a general failure.

Cause

On 2026-10-10 the OpenCode Console moved budgets into Controls → Policies (changelog: "Budgets have a new home — Controls → Policies replaces the old workspace, member and service account budget settings, including default limits and shared budgets.").

The Console's own UI no longer calls budgets/org; it calls:

GET /console/api/policies/current-budgets  -> 200
GET /console/api/policies                  -> 200

The old route is retired:

GET /console/api/budgets/org               -> 409 {"_tag":"Conflict"}

This is not auth and not a missing budget:

  • The same OAuth token + same x-org-id returns 200 on billing/status, usage/cost-by-day, policies and policies/current-budgets.
  • Correct org id → 409; a wrong org id → 403. So the 409 is the route itself, not permissions.
  • A workspace budget was configured during the probe.
  • fetchConsoleRoute (opencode-zen.js) tolerates 403/empty (the [bug]: budgets/org returns null without an org budget → permanent "Could not parse" error for opencode-zen #297 fix) but not 409, so the 409 surfaces and monthlyLimit falls back to creditLimit (which is null), leaving no limit shown.

New shape

GET /console/api/policies/current-budgets:

[{"policyID":"policy_legacy_budget_88030",
  "ruleID":"rule_legacy_budget_88030",
  "limitDollars":30,
  "scope":"combined",
  "per":"set",
  "spentDollars":2.73543333,
  "modelCount":0}]

Differences from budgets/org:

  • it is an array of policies, not a single object;
  • limitDollars / spentDollars are in dollars, not micro-cents;
  • scope is combined (one shared pool) or each (per member); per is set;
  • period ("month") and the reset live in GET /api/policies — current-budgets has no resetsAt;
  • it returns the workspace (combined) and member (each) policies, but not service-account policies.

Suggested fix

  • Call policies/current-budgets instead of budgets/org.
  • Parse limitDollars / spentDollars as dollars; prefer the scope:"combined" entry for a single "monthly limit" figure.
  • Stopgap: treat 409 like 403/empty (no budget → fall back to the credit limit) so the error stops surfacing while the new endpoint is wired in.

Activity

  1. vmvarela commented on Oct 12, 2026

    @vmvarela
    Contributor

    This is addressed in PR #322. It replaces the retired budgets/org request with the authenticated member policies endpoint, validates the member identity, and reports the most restrictive applicable monthly budget, including a shared workspace cap. Policies the plugin cannot safely evaluate are not shown as an effective limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions