Invalid time value error on Stripe webhook #1074

Closed
opened 2026-03-13 08:21:28 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @abrahamcarvalhoo on GitHub (Apr 18, 2025).

Originally assigned to: @ping-maxwell on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Set up Better Auth with the Stripe plugin and enable subscriptions.
  2. Add a free trial period to your Stripe plan (freeTrial: { days: 7 }).
  3. Use authClient.subscription.upgrade to start a subscription with trial.
  4. Wait for checkout.session.completed webhook to be triggered.
  5. The webhook route /api/auth/stripe/webhook crashes on onCheckoutSessionCompleted due to Invalid time value error.

Logs:
[Better Auth]: Stripe webhook failed. Error: Invalid time value

Current vs. Expected behavior

⚠️ Current vs. Expected behavior

Current Behavior:
When checkout.session.completed fires and subscription.trial_start or trial_end is undefined, calling new Date(undefined * 1000) inside onCheckoutSessionCompleted throws Invalid time value and the webhook fails.

This causes trialStart and trialEnd to remain NULL in the database, and the user never gets marked as trialing.

Expected Behavior:
The webhook should safely handle cases where Stripe returns no trial timestamps and avoid creating Invalid Date. The DB should be updated properly when there's a trial, or skip trial fields if not present.

What version of Better Auth are you using?

1.2.7

Provide environment information

- OS: Windows 11
- Browser: Chrome latest
- Hosting: Vercel
- DB: Neon Postgres
- Node.js: 22.x

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

Backend, Package, Types

Auth config (if applicable)

import { betterAuth } from "better-auth";
import { stripe } from "@better-auth/stripe";

export const auth = betterAuth({
  emailAndPassword: { enabled: true },
  plugins: [
    stripe({
      stripeClient,
      stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
      subscription: {
        enabled: true,
        plans: [
          {
            name: "Pro",
            priceId: "price_123",
            freeTrial: {
              days: 7,
            },
          },
        ],
      },
    }),
  ],
});

Additional context

  • The trial_start and trial_end fields in Stripe are sometimes undefined.
  • Attempting to use new Date(undefined * 1000) fails silently unless logged manually.
  • Updating onCheckoutSessionCompleted with null checks would resolve it.

Suggested fix:

const trialStart = subscription.trial_start != null ? new Date(subscription.trial_start * 1000) : undefined;
const trialEnd = subscription.trial_end != null ? new Date(subscription.trial_end * 1000) : undefined;
Originally created by @abrahamcarvalhoo on GitHub (Apr 18, 2025). Originally assigned to: @ping-maxwell on GitHub. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Set up Better Auth with the Stripe plugin and enable subscriptions. 2. Add a free trial period to your Stripe plan (`freeTrial: { days: 7 }`). 3. Use `authClient.subscription.upgrade` to start a subscription with trial. 4. Wait for `checkout.session.completed` webhook to be triggered. 5. The webhook route `/api/auth/stripe/webhook` crashes on `onCheckoutSessionCompleted` due to `Invalid time value` error. Logs: `[Better Auth]: Stripe webhook failed. Error: Invalid time value` ### Current vs. Expected behavior ### ⚠️ **Current vs. Expected behavior** **Current Behavior:** When `checkout.session.completed` fires and `subscription.trial_start` or `trial_end` is `undefined`, calling `new Date(undefined * 1000)` inside `onCheckoutSessionCompleted` throws `Invalid time value` and the webhook fails. This causes `trialStart` and `trialEnd` to remain `NULL` in the database, and the user never gets marked as `trialing`. **Expected Behavior:** The webhook should safely handle cases where Stripe returns no trial timestamps and avoid creating `Invalid Date`. The DB should be updated properly when there's a trial, or skip trial fields if not present. ### What version of Better Auth are you using? 1.2.7 ### Provide environment information ```bash - OS: Windows 11 - Browser: Chrome latest - Hosting: Vercel - DB: Neon Postgres - Node.js: 22.x ``` ### Which area(s) are affected? (Select all that apply) Backend, Package, Types ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth"; import { stripe } from "@better-auth/stripe"; export const auth = betterAuth({ emailAndPassword: { enabled: true }, plugins: [ stripe({ stripeClient, stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!, subscription: { enabled: true, plans: [ { name: "Pro", priceId: "price_123", freeTrial: { days: 7, }, }, ], }, }), ], }); ``` ### Additional context - The `trial_start` and `trial_end` fields in Stripe are sometimes `undefined`. - Attempting to use `new Date(undefined * 1000)` fails silently unless logged manually. - Updating `onCheckoutSessionCompleted` with null checks would resolve it. Suggested fix: ```ts const trialStart = subscription.trial_start != null ? new Date(subscription.trial_start * 1000) : undefined; const trialEnd = subscription.trial_end != null ? new Date(subscription.trial_end * 1000) : undefined;
GiteaMirror added the bugduplicate labels 2026-03-13 08:21:28 -05:00
Author
Owner

@abrahamcarvalhoo commented on GitHub (Apr 19, 2025):

Just use stripe 17.7.0 on packages, the new version 18 not working yet, broken the code. I’m using better auth v1.2.6

@abrahamcarvalhoo commented on GitHub (Apr 19, 2025): Just use stripe 17.7.0 on packages, the new version 18 not working yet, broken the code. I’m using better auth v1.2.6
Author
Owner

@ping-maxwell commented on GitHub (Apr 20, 2025):

I'm closing this as duplicate.
please refer to this PR as it will solve v18 stripe changes:
https://github.com/better-auth/better-auth/issues/2345

@ping-maxwell commented on GitHub (Apr 20, 2025): I'm closing this as duplicate. please refer to this PR as it will solve v18 stripe changes: https://github.com/better-auth/better-auth/issues/2345
Author
Owner

@JE4GLE commented on GitHub (May 8, 2025):

@ping-maxwell

I'm closing this as duplicate.
please refer to this PR as it will solve v18 stripe changes:
https://github.com/better-auth/better-auth/issues/2345

You are referring to this issue and not a PR. Could you post the PR, which will solve v18 stripe changes?

@JE4GLE commented on GitHub (May 8, 2025): @ping-maxwell > I'm closing this as duplicate. please refer to this PR as it will solve v18 stripe changes: https://github.com/better-auth/better-auth/issues/2345 You are referring to this issue and not a PR. Could you post the PR, which will solve v18 stripe changes?
Author
Owner

@ping-maxwell commented on GitHub (May 10, 2025):

Hey @JE4GLE, it's been merged: https://github.com/better-auth/better-auth/pull/2366

@ping-maxwell commented on GitHub (May 10, 2025): Hey @JE4GLE, it's been merged: https://github.com/better-auth/better-auth/pull/2366
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1074