Stripe Plugin: listActiveSubscriptions always returns default priceId instead of actual subscription priceId #2797

Open
opened 2026-03-13 10:20:55 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @k-urtica on GitHub (Jan 31, 2026).

Originally assigned to: @bytaesu on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Set up Stripe plugin with a plan that has both priceId (monthly) and annualDiscountPriceId (annual) Create a subscription with monthly billing
  2. Upgrade the subscription to annual billing using subscription.upgrade({ annual: true, subscriptionId: 'xxxx' }) Call listActiveSubscriptions API
  3. Observe that the returned priceId is still the monthly priceId, not the annualDiscountPriceId

Current vs. Expected behavior

Current Behavior

The listActiveSubscriptions API always returns the plan's default priceId (monthly price) regardless of the actual subscription billing cycle.

Expected Behavior

The API should return the actual current priceId from the Stripe subscription,
enabling applications to correctly determine whether a user is on monthly or annual billing.

What version of Better Auth are you using?

1.4.18

System info

{
  "system": {
    "platform": "linux",
    "arch": "x64",
    "version": "#1 SMP Tue Nov 5 00:21:55 UTC 2024",
    "release": "5.15.167.4-microsoft-standard-WSL2",
    "cpuCount": 6,
    "cpuModel": "Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz",
    "totalMemory": "11.69 GB",
    "freeMemory": "3.79 GB"
  },
  "node": {
    "version": "v24.11.1",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.6.2"
  },
  "frameworks": [
    {
      "name": "vue",
      "version": "3.5.27"
    },
    {
      "name": "nuxt",
      "version": "4.2.2"
    }
  ],
  "databases": [
    {
      "name": "@libsql/client",
      "version": "0.17.0"
    },
    {
      "name": "drizzle",
      "version": "0.45.1"
    }
  ],
  "betterAuth": {
    "version": "1.4.18",
    "config": null
  }
}

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

Backend, Client

Auth config (if applicable)


Additional context

No response

Originally created by @k-urtica on GitHub (Jan 31, 2026). Originally assigned to: @bytaesu on GitHub. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Set up Stripe plugin with a plan that has both `priceId` (monthly) and `annualDiscountPriceId` (annual) Create a subscription with monthly billing 2. Upgrade the subscription to annual billing using `subscription.upgrade({ annual: true, subscriptionId: 'xxxx' })` Call listActiveSubscriptions API 3. Observe that the returned priceId is still the monthly priceId, not the annualDiscountPriceId ### Current vs. Expected behavior #### Current Behavior The listActiveSubscriptions API always returns the plan's default priceId (monthly price) regardless of the actual subscription billing cycle. #### Expected Behavior The API should return the actual current priceId from the Stripe subscription, enabling applications to correctly determine whether a user is on monthly or annual billing. ### What version of Better Auth are you using? 1.4.18 ### System info ```bash { "system": { "platform": "linux", "arch": "x64", "version": "#1 SMP Tue Nov 5 00:21:55 UTC 2024", "release": "5.15.167.4-microsoft-standard-WSL2", "cpuCount": 6, "cpuModel": "Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz", "totalMemory": "11.69 GB", "freeMemory": "3.79 GB" }, "node": { "version": "v24.11.1", "env": "development" }, "packageManager": { "name": "npm", "version": "11.6.2" }, "frameworks": [ { "name": "vue", "version": "3.5.27" }, { "name": "nuxt", "version": "4.2.2" } ], "databases": [ { "name": "@libsql/client", "version": "0.17.0" }, { "name": "drizzle", "version": "0.45.1" } ], "betterAuth": { "version": "1.4.18", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Backend, Client ### Auth config (if applicable) ```typescript ``` ### Additional context _No response_
GiteaMirror added the plugin label 2026-03-13 10:20:55 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Jan 31, 2026):

It looks like you're encountering an issue where the listActiveSubscriptions API is returning the default priceId instead of the actual priceId reflecting the user's current subscription billing cycle.

From previous discussions, it seems this might be related to a recent bug that affected how the priceId is handled during upgrades and subscription updates. In the past, there was a fix implemented to ensure that the priceId is correctly updated and stored whenever a subscription is completed or updated [8], [12]. This suggests that the API should reflect the actual status of subscriptions after any changes.

To troubleshoot your specific case, I recommend checking the following steps:

  1. Ensure that you are correctly passing the subscriptionId when performing the upgrade using subscription.upgrade. This is important so that it updates the right subscription record.
  2. Verify whether the priceId is being stored correctly in your database at the time of subscription creation and updates. The implementation should maintain synchronization between your database and Stripe's information [13].
  3. If the problem persists, consider looking into related issues or feature requests in the GitHub repository to see if there might be any open discussions or known bugs that align with your experience.

If you’d like more specific help, tagging @bekacru or @ping__ may yield quicker answers from the Better Auth development team. What specific steps have you tried so far to resolve this issue?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Jan 31, 2026): It looks like you're encountering an issue where the `listActiveSubscriptions` API is returning the default priceId instead of the actual priceId reflecting the user's current subscription billing cycle. From previous discussions, it seems this might be related to a recent bug that affected how the priceId is handled during upgrades and subscription updates. In the past, there was a fix implemented to ensure that the `priceId` is correctly updated and stored whenever a subscription is completed or updated [[8]](https://github.com/better-auth/better-auth/pull/3239), [[12]](https://www.better-auth.com/docs/plugins/stripe). This suggests that the API should reflect the actual status of subscriptions after any changes. To troubleshoot your specific case, I recommend checking the following steps: 1. Ensure that you are correctly passing the subscriptionId when performing the upgrade using `subscription.upgrade`. This is important so that it updates the right subscription record. 2. Verify whether the `priceId` is being stored correctly in your database at the time of subscription creation and updates. The implementation should maintain synchronization between your database and Stripe's information [[13]](https://github.com/better-auth/better-auth/pull/7371). 3. If the problem persists, consider looking into related issues or feature requests in the GitHub repository to see if there might be any open discussions or known bugs that align with your experience. If you’d like more specific help, tagging @bekacru or @ping__ may yield quicker answers from the Better Auth development team. What specific steps have you tried so far to resolve this issue? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) • [Discord](https://discord.gg/better-auth) • [GitHub](https://github.com/better-auth/better-auth) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/better-auth_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/better-auth) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/better-auth/better-auth)
Author
Owner

@dosubot[bot] commented on GitHub (Jan 31, 2026):

This is a known limitation: the Stripe plugin's listActiveSubscriptions API always returns the plan's default priceId (usually the monthly one), not the actual priceId from the Stripe subscription after an upgrade. This happens because the API enriches local subscription records with the plan's static priceId, not the live Stripe subscription data, so it can't reflect changes like switching to annual billing. There’s currently no interval or billing frequency field in the returned object either, so you can’t distinguish monthly vs annual directly from the API response [discussion].

Workarounds:

  • Fetch the real priceId directly from Stripe using the subscription's stripeSubscriptionId, then use that to determine the billing interval.
  • Use separate Stripe products or plan names for monthly and annual plans, so the plan name itself indicates the interval.
  • You could try inferring the interval by comparing periodStart and periodEnd, but this is not reliable for all cases [issue].

If you need to distinguish billing intervals in your app, you’ll need to implement one of these workarounds for now. There are open discussions and issues about improving this, but as of 1.4.18, the API does not return the actual Stripe priceId [source code].

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Jan 31, 2026): <!-- Answer --> This is a known limitation: the Stripe plugin's listActiveSubscriptions API always returns the plan's default priceId (usually the monthly one), not the actual priceId from the Stripe subscription after an upgrade. This happens because the API enriches local subscription records with the plan's static priceId, not the live Stripe subscription data, so it can't reflect changes like switching to annual billing. There’s currently no interval or billing frequency field in the returned object either, so you can’t distinguish monthly vs annual directly from the API response [[discussion](https://github.com/better-auth/better-auth/discussions/7220)]. Workarounds: - Fetch the real priceId directly from Stripe using the subscription's stripeSubscriptionId, then use that to determine the billing interval. - Use separate Stripe products or plan names for monthly and annual plans, so the plan name itself indicates the interval. - You could try inferring the interval by comparing periodStart and periodEnd, but this is not reliable for all cases [[issue](https://github.com/better-auth/better-auth/issues/3235)]. If you need to distinguish billing intervals in your app, you’ll need to implement one of these workarounds for now. There are open discussions and issues about improving this, but as of 1.4.18, the API does not return the actual Stripe priceId [[source code](https://github.com/better-auth/better-auth/blob/583f12fb7db38681ee882d219ce3895faa4a6976/packages/stripe/src/routes.ts#L1236-L1290)]. <!-- 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/56c939f3-854d-41ed-aac5-29bc53282c30?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/56c939f3-854d-41ed-aac5-29bc53282c30?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/56c939f3-854d-41ed-aac5-29bc53282c30?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/56c939f3-854d-41ed-aac5-29bc53282c30?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/56c939f3-854d-41ed-aac5-29bc53282c30?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/56c939f3-854d-41ed-aac5-29bc53282c30?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/56c939f3-854d-41ed-aac5-29bc53282c30?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20a%20known%20limitation%3A%20the%20Stripe%20plugin%27s%20listActiveSubscriptions%20API%20always%20returns%20the%20plan%27s%20default%20priceId%20%28usually%20the%20monthly%20one%29%2C%20not%20the%20actual%20priceId%20from%20the%20Stripe%20subscription%20after%20an%20upgrade.%20This%20happens%20because%20the%20API%20enriches%20local%20subscription%20records%20with%20the%20plan%27s%20static%20priceId%2C%20not%20the%20live%20Stripe%20subscription%20data%2C%20so%20it%20can%27t%20reflect%20changes%20like%20switching%20to%20annual%20billing.%20There%E2%80%99s%20currently%20no%20interval%20or%20billing%20frequency%20field%20in%20the%20returned%20object%20either%2C%20so%20you%20can%E2%80%99t%20distinguish%20monthly%20vs%20annual%20directly%20from%20the%20API%20response%20%5B%5Bdiscussion%5D%28https%3A//github.com/better-auth/better-auth/discussions/7220%29%5D.%0A%0AWorkarounds%3A%20%20%0A-%20Fetch%20the%20real%20priceId%20directly%20from%20Stripe%20using%20the%20subscription%27s%20stripeSubscriptionId%2C%20then%20use%20that%20to%20determine%20the%20billing%20interval.%0A-%20Use%20separate%20Stripe%20products%20or%20plan%20names%20for%20monthly%20and%20annual%20plans%2C%20so%20the%20plan%20name%20itself%20indicates%20the%20interval.%0A-%20You%20could%20try%20inferring%20the%20interval%20by%20comparing%20periodStart%20and%20periodEnd%2C%20but%20this%20is%20not%20reliable%20for%20all%20cases%20%5B%5Bissue%5D%28https%3A//github.com/better-auth/better-auth/issues/3235%29%5D.%0A%0AIf%20you%20need%20to%20distinguish%20billing%20intervals%20in%20your%20app%2C%20you%E2%80%99ll%20need%20to%20implement%20one%20of%20these%20workarounds%20for%20now.%20There%20are%20open%20discussions%20and%20issues%20about%20improving%20this%2C%20but%20as%20of%201.4.18%2C%20the%20API%20does%20not%20return%20the%20actual%20Stripe%20priceId%20%5B%5Bsource%20code%5D%28https%3A//github.com/better-auth/better-auth/blob/583f12fb7db38681ee882d219ce3895faa4a6976/packages/stripe/src/routes.ts%23L1236-L1290%29%5D.)&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/7721)
Author
Owner

@bytaesu commented on GitHub (Jan 31, 2026):

Hi @k-urtica,

The Stripe subscription object has many fields, so we are only storing those that affect the flow. With the stripeSubscriptionId, you can fetch the full object if needed.

If the goal is to determine the billingInterval, I can finish my draft PR and incorporate it. Feel free to let me know 😄

@bytaesu commented on GitHub (Jan 31, 2026): Hi @k-urtica, The Stripe subscription object has many fields, so we are only storing those that affect the flow. With the `stripeSubscriptionId`, you can fetch the full object if needed. If the goal is to determine the `billingInterval`, I can finish my draft PR and incorporate it. Feel free to let me know 😄 - https://github.com/better-auth/better-auth/pull/7221
Author
Owner

@k-urtica commented on GitHub (Jan 31, 2026):

@bytaesu
Thanks for the explanation! I appreciate you considering the billingInterval feature - that would indeed solve my immediate need to distinguish between monthly and annual billing.

I'd be happy to see that PR completed, as having this functionality built-in would be much cleaner than the current workaround of calling the Stripe API directly.

That said, I still have a fundamental concern about listActiveSubscriptions - it returns plan?.priceId regardless of the actual subscription state. This creates a mismatch between what the API name suggests ("list active subscriptions") and what it actually returns.

The current implementation returns misleading information - showing monthly pricing even for users on annual plans. This doesn't reflect the true subscription state and could confuse developers expecting accurate subscription data.

@k-urtica commented on GitHub (Jan 31, 2026): @bytaesu Thanks for the explanation! I appreciate you considering the `billingInterval` feature - that would indeed solve my immediate need to distinguish between monthly and annual billing. I'd be happy to see that PR completed, as having this functionality built-in would be much cleaner than the current workaround of calling the Stripe API directly. That said, I still have a fundamental concern about `listActiveSubscriptions` - it returns `plan?.priceId` regardless of the actual subscription state. This creates a mismatch between what the API name suggests ("list active subscriptions") and what it actually returns. The current implementation returns misleading information - showing monthly pricing even for users on annual plans. This doesn't reflect the true subscription state and could confuse developers expecting accurate subscription data.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2797