[GH-ISSUE #3236] Bad Request when upgrading subscription with identical plan/seats from monthly to yearly #26857

Closed
opened 2026-04-17 17:34:40 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @MikeCodeur on GitHub (Jul 1, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/3236

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

The authClient.subscription.upgrade() function allows upgrading between monthly and yearly billing modes, and changing the number of seats without issues. However, when attempting to upgrade a subscription with the same plan and same number of seats but changing from monthly to yearly (or vice versa), the API returns a Bad Request error.

Steps to Reproduce

  1. Create a monthly subscription

    • Create a Pro subscription with 5 seats in monthly mode
    • Verify the subscription is active
  2. Attempt to upgrade to yearly with same plan/seats

    • Use authClient.subscription.upgrade() with:
      • Same plan (Pro)
      • Same number of seats (5)
      • annual: true (changing from monthly to yearly)
    • Observe that the API returns a Bad Request error
  3. Verify other upgrade scenarios work

    • Change seats only (monthly, 5 → 10 seats): Works
    • Change plan only (Pro → Enterprise, monthly): Works
    • Change billing mode only (monthly → yearly, different seats): Works

Current vs. Expected behavior

Expected Behavior

  • The upgrade should succeed when changing only the billing mode (monthly ↔ yearly)
  • The API should accept the request even if plan and seats remain identical
  • The subscription should be updated with the new billing cycle

Actual Behavior

  • The API returns a Bad Request error
  • The upgrade fails when plan and seats are identical but billing mode changes
  • Other upgrade scenarios (different plans, different seats) work correctly

What version of Better Auth are you using?

1.2.12

Provide environment information

-WSL2

Which area(s) are affected? (Select all that apply)

Client

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @MikeCodeur on GitHub (Jul 1, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/3236 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce The `authClient.subscription.upgrade()` function allows upgrading between monthly and yearly billing modes, and changing the number of seats without issues. However, when attempting to upgrade a subscription with the same plan and same number of seats but changing from monthly to yearly (or vice versa), the API returns a Bad Request error. ## Steps to Reproduce 1. **Create a monthly subscription** - Create a Pro subscription with 5 seats in monthly mode - Verify the subscription is active 2. **Attempt to upgrade to yearly with same plan/seats** - Use `authClient.subscription.upgrade()` with: - Same plan (Pro) - Same number of seats (5) - `annual: true` (changing from monthly to yearly) - Observe that the API returns a Bad Request error 3. **Verify other upgrade scenarios work** - Change seats only (monthly, 5 → 10 seats): Works - Change plan only (Pro → Enterprise, monthly): Works - Change billing mode only (monthly → yearly, different seats): Works ### Current vs. Expected behavior ## Expected Behavior - The upgrade should succeed when changing only the billing mode (monthly ↔ yearly) - The API should accept the request even if plan and seats remain identical - The subscription should be updated with the new billing cycle ## Actual Behavior - The API returns a Bad Request error - The upgrade fails when plan and seats are identical but billing mode changes - Other upgrade scenarios (different plans, different seats) work correctly ### What version of Better Auth are you using? 1.2.12 ### Provide environment information ```bash -WSL2 ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the lockedbug labels 2026-04-17 17:34:40 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jul 1, 2025):

This Bad Request error is caused by a check in the upgrade logic that prevents duplicate subscriptions with the same plan and seat count—even if you’re only changing the billing mode (monthly ↔ yearly). The validation treats a billing mode change alone as insufficient for an upgrade, so the request is rejected if plan and seats are unchanged see details.

Other upgrade scenarios (changing seats or plan) work because they bypass this duplicate check. There isn’t a documented workaround for upgrading only the billing mode with identical plan and seats, and the annual: true parameter does not bypass this logic reference.

If you need to change the billing mode, you may need to adjust the seat count or plan as part of the upgrade, or wait for a future update that supports this scenario. If you’re running into this as a blocker, you might want to track related issues like this one, where similar subscription upgrade constraints were discussed.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Join Discord Share on X

<!-- gh-comment-id:3023958890 --> @dosubot[bot] commented on GitHub (Jul 1, 2025): <!-- Answer --> This Bad Request error is caused by a check in the upgrade logic that prevents duplicate subscriptions with the same plan and seat count—even if you’re only changing the billing mode (monthly ↔ yearly). The validation treats a billing mode change alone as insufficient for an upgrade, so the request is rejected if plan and seats are unchanged [see details](https://github.com/better-auth/better-auth/pull/2967). Other upgrade scenarios (changing seats or plan) work because they bypass this duplicate check. There isn’t a documented workaround for upgrading only the billing mode with identical plan and seats, and the `annual: true` parameter does not bypass this logic [reference](https://github.com/better-auth/better-auth/pull/1725). If you need to change the billing mode, you may need to adjust the seat count or plan as part of the upgrade, or wait for a future update that supports this scenario. If you’re running into this as a blocker, you might want to track related issues like [this one](https://github.com/better-auth/better-auth/issues/2929), where similar subscription upgrade constraints were discussed. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/580ac9d9-ffff-46c0-843f-d3c14ad3ef4b?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/580ac9d9-ffff-46c0-843f-d3c14ad3ef4b?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/580ac9d9-ffff-46c0-843f-d3c14ad3ef4b?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/580ac9d9-ffff-46c0-843f-d3c14ad3ef4b?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/580ac9d9-ffff-46c0-843f-d3c14ad3ef4b?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/580ac9d9-ffff-46c0-843f-d3c14ad3ef4b?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/580ac9d9-ffff-46c0-843f-d3c14ad3ef4b?feedback_type=other)</sup>&nbsp;&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/3236)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#26857