feat(billing): add stripe error translator - #1849
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe billing errors package adds typed provider error classifications, Stripe and network error translation, provider metadata preservation, multi-error unwrapping, and comprehensive translation tests. ChangesStripe error translation
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related issues
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 82a368c6-6d6a-499a-a7ee-c5424a35fde6
📒 Files selected for processing (2)
billing/stripe_errors.gobilling/stripe_errors_test.go
Coverage Report for CI Build 30974209276Coverage increased (+0.03%) to 47.559%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
1020777 to
365f094
Compare
|
Tested the full stack (#1849 translator -> #1850 service translation -> #1851 handler mapper) live against a local Frontier with real Stripe test mode. Fresh org owned by a normal user; org-level calls made with that user's session, admin calls with a platform admin. Note: DelegatedCheckout is an AdminService RPC — the caller in those rows is a platform admin or internal automation, not the end user. New error codes, all verified live (every one of these was
The common thread:
Happy paths regressed nothing: account create/get/list/update, balance, checkout sessions (real Stripe URLs), delegated subscription (went active, card charged), plan change with scheduled phase, cancel upcoming phase, cancel subscription, upcoming invoice, HasTrialed. Unchanged codes confirmed: Testing also surfaced four cases that still returned
All re-verified live after the fix. |
|
One follow-up on the test report above (commit 8709ad9 on #1851): provider messages passed through to the caller now mask provider-generated object ids. A deleted customer reads as "No such customer: 'cus_*****'" instead of showing the real Stripe customer id. Caller-supplied values don't match the id shape, so "No such coupon: 'SUMMER20'" is unchanged. Covered by unit tests on the mapper. |
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a52c06a8-3382-41ea-97ea-bb029f124b94
📒 Files selected for processing (2)
billing/errors/errors.gobilling/errors/errors_test.go
rohilsurana
left a comment
There was a problem hiding this comment.
Reviewed the whole stack (#1849 -> #1850 -> #1851). This one looks good. Small package with one clear job, and the table tests cover the classification well, including wrapped errors and keeping the kinds apart.
Notes:
- Package name
errorswith thebillingerrorsimport alias matches thecore/userpat/errorsconvention. Works for me. - Classification precedence looks right: resource missing first, then card/decline, then availability. I checked stripe-go v79: it has no rate limit error type, so matching on the code plus HTTP 429/5xx is the right way with this SDK.
A few small comments inline.
Add a billing/errors package that classifies stripe errors into typed provider errors: resource_missing means the record is gone on the provider, card errors mean the payment failed, and rate limits or stripe outages mean the provider is unavailable. The translated error keeps stripe's human-readable message and the original error chain. Part of #1836. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review fixes: connection failures and timeouts reaching stripe now translate to provider-unavailable (a canceled request stays as is), the stripe request id is kept on ProviderError for support lookups, and Unwrap no longer returns a slice with a nil entry when the error was built without a cause. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
9722125 to
eaeb365
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: c4f368ca-f379-462a-ba5f-b33e7c7d2205
📒 Files selected for processing (2)
billing/errors/errors.gobilling/errors/errors_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
- billing/errors/errors.go
What
Adds a
billing/errorspackage (imported asbillingerrors, same convention ascore/userpat/errors) with three typed errors and one function,TranslateStripeError, that classifies a stripe error into them:resource_missing→ErrProviderResourceMissing(the record is gone on Stripe)ErrPaymentFailedErrProviderUnavailableAnything else is returned unchanged.
The translated error is a
ProviderError. Its message keeps Stripe's human-readable text (stripe.Error.Msg) instead of the raw JSON blob thatstripe.Error.Error()prints. The original error stays in the chain, soerrors.Ascan still reach thestripe.Errorwhen needed.Why
Almost every billing failure today reaches the caller as a bare "internal server error", even when the problem is the state of their billing account (see #1836). This translator is the first layer of the fix: it gives the services and handlers a typed error they can act on.
Part of #1836. Stack: this PR → services adopt the translator → handlers map the errors to proper codes.
🤖 Generated with Claude Code