Skip to content

feat(seer-billing): Handle SeerOutOfCreditsException at Autofix callers - #130284

Merged
srest2021 merged 67 commits into
masterfrom
srest2021/CW-3061-autofix-out-of-credits
Nov 10, 2026
Merged

srest2021 merged 67 commits into
masterfrom
srest2021/CW-3061-autofix-out-of-credits

Conversation

@srest2021

@srest2021 srest2021 commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

Fixes CW-3061

Handles the SeerOutOfCreditsException exception from #130283 at every caller. Quota is only checked when a new run starts, so "not checked" means a continuation.

User triggered

Caller Out of credits Out of quota
Issue page / API: start or continue a step 402 Start: 402. Continue: not checked
Issue page / API: open PR 402 Not checked
Issue page: PR feedback 402 before queueing, so the feedback isn't dropped later (see "PR iteration: queued feedback" below) Not checked
Seer chat: reply to a single run 402, same as a chat message Not checked
Slack buttons Error reply, recorded as a halt Start: error reply, recorded as a failure. Continue: not checked
Admin: single run 400 400
Admin: retry a failed step Skipped with a reason Not checked

Automatically triggered

Caller Out of credits Out of quota
New issue automation N/A, ignored N/A, ignored
Completion hook: automatic next step, automatic open PR Log and stop Not checked
PR iteration: queued feedback Skip and discard the iteration Not checked
PR iteration: push, branch-moved retry Log, not pushed. The iteration ends as push_failed, without pausing iteration Not checked
Agentic triage Not checked, stays free Free cohort skips it

Note: The PR iteration behavior doesn't have good UX yet. When a push or retry is refused for credits, the user sees nothing and the PR isn't updated. When Seer itself stops an iteration for credits, iteration on the PR is paused for good, even after a top-up. See CW-3066 for planned followup work

Return a 402 before sending a chat message when a token-billed org does not have enough Seer credits. Dashboard generation runs are not gated. can_run_seer_operation now passes orgs that are not token-billed.

Refs CW-3061
Token-billed orgs are checked for Seer credits before each Autofix step and before opening a PR, and get SeerOutOfCreditsException when they can't pay. Other orgs keep the seat-based quota check. Agentic triage runs are not gated.

Refs CW-3061
The issue page returns a 402, Slack shows an error, the admin endpoints report it, and automatic paths (new issue automation, completion hook, PR iteration) log and stop.

Refs CW-3061
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Nov 6, 2026
@linear-code

linear-code Bot commented Nov 6, 2026

Copy link
Copy Markdown

CW-3061

@sentry

sentry Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Sentry Snapshot Testing

Name Added Removed Changed Renamed Unchanged Skipped Status
sentry-frontend
sentry-frontend
0 0 0 0 804 0 ✅ Unchanged

⚙️ sentry-frontend Snapshot Settings

…gent-chat

# Conflicts:
#	src/sentry/seer/endpoints/organization_seer_agent_chat.py
…tofix-gating

# Conflicts:
#	src/sentry/seer/autofix/feature/dispatch.py
#	tests/sentry/seer/autofix/feature/test_dispatch.py
…1-autofix-out-of-credits

# Conflicts:
#	src/sentry/seer/endpoints/group_ai_autofix.py
Chat replies to single runs continue the run through continue_single_run, which skipped billing. The run's own referrer decides, so agentic triage runs stay free.
…gent-chat

# Conflicts:
#	src/sentry/seer/endpoints/organization_seer_agent_chat.py
…tofix-gating

Check the credit check flag before the token-billed flag. has_enough_seer_credits no longer checks the flag; its callers do.
…1-autofix-out-of-credits

# Conflicts:
#	src/sentry/seer/entrypoints/operator.py
#	tests/sentry/seer/endpoints/test_group_ai_autofix.py
Cover orgs that aren't token-billed, group the chat credit tests after the access tests, and match the neighboring tests' names and setup.
…utofix-gating

# Conflicts:
#	src/sentry/seer/credits.py
Single runs are behind organizations:autofix-single-run and need their own estimate, so they're out of scope here.

@billyvg billyvg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI-assisted review, posted on behalf of @billyvg.

trigger_autofix_agent checked billing, then called trigger_autofix_feature, which checked it again with the same arguments. Keep only the dispatch check, and test a token-billed org with credit checks off.
srest2021 added a commit that referenced this pull request Nov 9, 2026
…tion (#130463)

relates to CW-2332

depends on #129563, #130283,
#130284

The chat's credit check only runs when the panel opens or the window
regains focus. If credits run out partway through a conversation, the
message box stays enabled and the next send fails with a generic error.

This rechecks credits when:
- Seer stops a reply for credits (`failure_reason: out_of_credits`)
- a send comes back 402

so the out-of-credits notice and disabled message box show right away. A
402 no longer shows "There was an error sending your message"; the
recheck brings up the notice instead.

The recheck invalidates the credit check query, like
`useExplorerAutofix` does. That needed `useSeerCreditCheck` to turn off
with `enabled` instead of `skipToken`, so the key is the same either
way.

Example (it would show any intermediate thinking as well):
<img width="402" height="615" alt="× Seer Agent I"
src="https://github.com/user-attachments/assets/c7e056e8-73a7-4a5a-be32-62bcb80e1609"
/>

---------

Co-authored-by: Billy Vong <billy@sentry.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
self.entrypoint.on_trigger_autofix_error(error=error)
lifecycle.record_failure(failure_reason=error)
return
except SeerOutOfCreditsException:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've cut out CW-3080 to track the work to post richer replies for this case. Thanks!

Credit checks no longer skip runs by referrer. Agentic triage runs are checked like any other until a follow-up marks them by feature instead. Credit checks are behind seer-credit-checks, so nothing changes in production.

Refs CW-3061
…' into srest2021/CW-3061-autofix-out-of-credits
@srest2021
srest2021 added this pull request to stack #130567 November 10, 2026 01:16
@srest2021 srest2021 changed the title feat(seer): Handle SeerOutOfCreditsException at Autofix callers feat(seer-billing): Handle SeerOutOfCreditsException at Autofix callers Nov 10, 2026
sentry-junior Bot and others added 5 commits November 10, 2026 18:19
…402s

Add a stable code to each billing 402 body (seer_out_of_credits,
seer_out_of_quota) so API clients like the CLI and MCP can branch on it
instead of the detail text. The out-of-quota response becomes a dict
with detail and code instead of a bare string.

Co-Authored-By: Sofia Rest <sofia.rest@sentry.io>
An operation only sets the credit estimate, since it can run under more than one feature, so callers pass the feature explicitly. The credit check endpoint now takes a feature param.
The UI can't tell runs agentic triage started apart yet, so the credit check endpoint picks the feature itself instead of requiring the UI to send it.
…' into srest2021/CW-3061-autofix-out-of-credits
@srest2021
srest2021 removed this pull request from stack #130567 November 10, 2026 19:35
srest2021 added a commit that referenced this pull request Nov 10, 2026
…130283)

Relates to CW-3061

Adds `check_autofix_billing`, called from all autofix entrypoints:
`trigger_autofix_agent`, `trigger_autofix_feature`,
`trigger_push_changes` and `continue_single_run`.

- Token-billed orgs are checked for credits before every step, before
Open PR and before a reply to a single run, and get
`SeerOutOfCreditsException` if they can't pay. All credit checks are
also separately feature-flagged.
- Other orgs keep the same quota check. 

Autofix single run replies get their own billable operation with a
placeholder estimate.

WIP followup to handle the out of credits exceptions:
#130284

---------

Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>
Base automatically changed from srest2021/CW-3061-autofix-gating to master November 10, 2026 19:42
@srest2021
srest2021 merged commit 1a9622c into master Nov 10, 2026
79 checks passed
@srest2021
srest2021 deleted the srest2021/CW-3061-autofix-out-of-credits branch November 10, 2026 21:08
BYK pushed a commit to getsentry/toolkit that referenced this pull request Nov 11, 2026
`sentry issue explain` and `sentry issue plan` treat every 402 from the
autofix endpoint as "Seer requires a paid plan" and offer a free trial.
An org on token-based billing that runs out of Seer credits gets that
message too. A run that starts and then stops for credits reads as
"Analysis completed but no root causes found" or "Plan creation failed".

- A 402 with `code: "seer_out_of_credits"` (added in
getsentry/sentry#130284) now raises a new `out_of_credits` Seer error.
Any other 402, including `seer_out_of_quota` and the 402 with no code
that older Sentry versions send, keeps the current no-budget error.
- A run that ends with `failure_reason: "out_of_credits"` raises the
same error from both commands.
- The error has its own exit code, 43, and is left out of the free trial
prompt.

What the user sees:

```
Your organization is out of Seer credits.

Someone with billing access can adjust Seer spend and auto-reload in Sentry:
  https://my-org.sentry.io/settings/billing/overview/?product=seer
```

A failed run is still retried on the next invocation, so someone who
topped up recovers by running the command again.

The 402 comes from getsentry/sentry#130283 and getsentry/sentry#130284,
which have both merged. Sentry's credit checks are behind the
`organizations:seer-credit-checks` flag, so for an org without it the
CLI behaves as it does today. The MCP equivalent is #2031.

Fixes CW-3075
srest2021 added a commit to getsentry/toolkit that referenced this pull request Nov 11, 2026
Fixes CW-2330

Depends on getsentry/sentry#130284

`analyze_issue_with_seer` now says why a run didn't start when Sentry
answers 402, for out-of-credits and out-of-quota orgs, instead of
returning an API error. It tells the two apart by `code`. A 402 without
the out-of-credits code, including the bare-string out-of-quota body
that Sentry sends before #130284, still reads as out of quota.

When a run stopped because the org ran out of credits
(`failure_reason=out_of_credits`), the tool and `get_issue_details` now
say why.

Until the Sentry PRs ship, a run that runs out of credits still starts
and then stops with `out_of_credits`, which this PR already explains.
Both Sentry checks are behind `organizations:seer-credit-checks`.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com>

This branch was successfully deployed

1 active deployment
Preview — f6ca995f Deployed Nov 10, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants