Polar customer portal creation failed ("invalid_union", "invalid_type", "ZodError") #1415

Closed
opened 2026-03-13 08:38:57 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @indieTrav on GitHub (Jun 24, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

NextJs 15 with better-auth (polar plugin) and polar.

Current vs. Expected behavior

In NextJS 15, with better-auth, and polar. I setup a sandbox account on polar, and when trying to open a customer portal from client component, I get this error on server below when clicking the button. Anyone know a fix?

  • The customer is in portal (Was created on signup
  • A subscription is created for the customer
  • Current subscription, customer info and product details fetch just fine.
  • I am not validating with Zod (as far as I know) the client component.

Server Error:

ERROR [Better Auth]: Polar customer portal creation failed. Error: Input validation failed: [
  {
    "code": "invalid_union",
    "unionErrors": [
      {
        "issues": [
          {
            "code": "invalid_type",
            "expected": "string",
            "received": "undefined",
            "path": [
              "customerId"
            ],
            "message": "Required"
          }
        ],
        "name": "ZodError"
      },
      {
        "issues": [
          {
            "code": "invalid_type",
            "expected": "string",
            "received": "undefined",
            "path": [
              "customerExternalId"
            ],
            "message": "Required"
          }
        ],
        "name": "ZodError"
      }
    ],
    "path": [],
    "message": "Invalid input"
  }
]

  • auth.ts
import * as schema from "@/db/schema";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db"; // your drizzle instance
import { sendChangeEmailVerificationEmail, sendPasswordResetEmail, sendVerificationEmail } from "./mail";
import { polar, checkout, portal } from "@polar-sh/better-auth";

import { polarClient } from "./polar";

export const auth = betterAuth({
  plugins: [
    polar({
      client: polarClient,
      createCustomerOnSignUp: true,
      use: [
        portal(),
        checkout({
          authenticatedUsersOnly: true,
          successUrl: '/dashboard/upgrade',
        }),
      ]
    })
  ],

...

polar.ts

import { Polar } from "@polar-sh/sdk";

export const polarClient = new Polar({
  accessToken: process.env.POLAR_ACCESS_TOKEN,
  server: 'sandbox'
});

auth.client.ts

import { inferAdditionalFields } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";
import { polarClient } from "@polar-sh/better-auth";
import type { auth } from "./auth";

export const authClient = createAuthClient({
  plugins: [
    polarClient(),
    inferAdditionalFields<typeof auth>()
  ],
});

client component:

"use client"

import { Button } from "@/components/ui/button"
import { authClient } from "@/lib/auth-client"
import { useTRPC } from "@/trpc/client";
import { useSuspenseQuery } from "@tanstack/react-query";

export const BillingView = () => {

  const trpc = useTRPC();

  const { data: products } = useSuspenseQuery(
    trpc.premium.getProducts.queryOptions()
  );

  const { data: currentSubscription } = useSuspenseQuery(
    trpc.premium.getCurrentSubscription.queryOptions()
  );

  console.log("Products: ", products)
  console.log("Current Subscriptions: ", currentSubscription)

  return (
    <div>
      <Button onClick={() => authClient.customer.portal()}>Billing View</Button>
    </div>
  )
}

When clicking Billing View Button, it produces the error.

What version of Better Auth are you using?

1.2.9

Provide environment information

- OS: Mac M1 Sequoia 15.5
- Browser: Brave 1.79.119 (Official Build) (arm64)

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

Client

Auth config (if applicable)

import * as schema from "@/db/schema";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/db"; // your drizzle instance
import { sendChangeEmailVerificationEmail, sendPasswordResetEmail, sendVerificationEmail } from "./mail";
import { polar, checkout, portal } from "@polar-sh/better-auth";

import { polarClient } from "./polar";

export const auth = betterAuth({
  plugins: [
    polar({
      client: polarClient,
      createCustomerOnSignUp: true,
      use: [
        portal(),
        checkout({
          authenticatedUsersOnly: true,
          successUrl: '/dashboard/upgrade',
        }),
      ]
    })
  ],
  emailAndPassword: {
    enabled: true,
    sendResetPassword: async ({ user, url, token }, request) => {
      await sendPasswordResetEmail(user.email, token);
    },
    requireEmailVerification: true
  },
  emailVerification: {
    sendOnSignUp: true,
    sendVerificationEmail: async ({ user, url, token }, request) => {
      await sendVerificationEmail(user.email, url)
    },
  },
  socialProviders: {
    google: {
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
    github: {
      clientId: process.env.GITHUB_CLIENT_ID as string,
      clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
    },
  },
  database: drizzleAdapter(db, {
    provider: "pg",
    schema: {
      ...schema,
    },
  }),
  user: {
    additionalFields: {
      role: {
        type: "string",
        required: false,
        defaultValue: "USER",
        input: false, // don't allow users to set role
      },
      hasAccess: {
        type: "boolean",
        required: false,
        defaultValue: false,
        input: false,
      },
    },
    changeEmail: {
      enabled: true,
      sendChangeEmailVerification: async ({ user, newEmail, url, token }, request) => {
        await sendChangeEmailVerificationEmail(user.email, url)
      }
    }
  },
});

type Session = typeof auth.$Infer.Session;

Additional context

Package.json versions:

  • "@polar-sh/sdk": "^0.32.16",
  • "better-auth": "^1.2.9",
  • "next": "15.3.3",

UPDATES

  • I noticed this error as well on the server "GET /api/auth/customer/portal 500" Unable to find the path, but I can't find the config for that anywhere in better-auth docs.
  • Someone in a discord group mentioned downgrading to version "@polar-sh/sdk": 0.32.16 , but I am on that version.
Originally created by @indieTrav on GitHub (Jun 24, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce NextJs 15 with better-auth (polar plugin) and polar. ### Current vs. Expected behavior In NextJS 15, with better-auth, and polar. I setup a sandbox account on polar, and when trying to open a customer portal from client component, I get this error on server below when clicking the button. Anyone know a fix? - [x] The customer is in portal (Was created on signup - [x] A subscription is created for the customer - [x] Current subscription, customer info and product details fetch just fine. - [x] I am not validating with Zod (as far as I know) the client component. Server Error: ``` ERROR [Better Auth]: Polar customer portal creation failed. Error: Input validation failed: [ { "code": "invalid_union", "unionErrors": [ { "issues": [ { "code": "invalid_type", "expected": "string", "received": "undefined", "path": [ "customerId" ], "message": "Required" } ], "name": "ZodError" }, { "issues": [ { "code": "invalid_type", "expected": "string", "received": "undefined", "path": [ "customerExternalId" ], "message": "Required" } ], "name": "ZodError" } ], "path": [], "message": "Invalid input" } ] ``` - auth.ts ```typescript import * as schema from "@/db/schema"; import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { db } from "@/db"; // your drizzle instance import { sendChangeEmailVerificationEmail, sendPasswordResetEmail, sendVerificationEmail } from "./mail"; import { polar, checkout, portal } from "@polar-sh/better-auth"; import { polarClient } from "./polar"; export const auth = betterAuth({ plugins: [ polar({ client: polarClient, createCustomerOnSignUp: true, use: [ portal(), checkout({ authenticatedUsersOnly: true, successUrl: '/dashboard/upgrade', }), ] }) ], ... ``` polar.ts ```typescript import { Polar } from "@polar-sh/sdk"; export const polarClient = new Polar({ accessToken: process.env.POLAR_ACCESS_TOKEN, server: 'sandbox' }); ``` auth.client.ts ```typescript import { inferAdditionalFields } from "better-auth/client/plugins"; import { createAuthClient } from "better-auth/react"; import { polarClient } from "@polar-sh/better-auth"; import type { auth } from "./auth"; export const authClient = createAuthClient({ plugins: [ polarClient(), inferAdditionalFields<typeof auth>() ], }); ``` client component: ```typescript "use client" import { Button } from "@/components/ui/button" import { authClient } from "@/lib/auth-client" import { useTRPC } from "@/trpc/client"; import { useSuspenseQuery } from "@tanstack/react-query"; export const BillingView = () => { const trpc = useTRPC(); const { data: products } = useSuspenseQuery( trpc.premium.getProducts.queryOptions() ); const { data: currentSubscription } = useSuspenseQuery( trpc.premium.getCurrentSubscription.queryOptions() ); console.log("Products: ", products) console.log("Current Subscriptions: ", currentSubscription) return ( <div> <Button onClick={() => authClient.customer.portal()}>Billing View</Button> </div> ) } ``` When clicking Billing View Button, it produces the error. ### What version of Better Auth are you using? 1.2.9 ### Provide environment information ```bash - OS: Mac M1 Sequoia 15.5 - Browser: Brave 1.79.119 (Official Build) (arm64) ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript import * as schema from "@/db/schema"; import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { db } from "@/db"; // your drizzle instance import { sendChangeEmailVerificationEmail, sendPasswordResetEmail, sendVerificationEmail } from "./mail"; import { polar, checkout, portal } from "@polar-sh/better-auth"; import { polarClient } from "./polar"; export const auth = betterAuth({ plugins: [ polar({ client: polarClient, createCustomerOnSignUp: true, use: [ portal(), checkout({ authenticatedUsersOnly: true, successUrl: '/dashboard/upgrade', }), ] }) ], emailAndPassword: { enabled: true, sendResetPassword: async ({ user, url, token }, request) => { await sendPasswordResetEmail(user.email, token); }, requireEmailVerification: true }, emailVerification: { sendOnSignUp: true, sendVerificationEmail: async ({ user, url, token }, request) => { await sendVerificationEmail(user.email, url) }, }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, github: { clientId: process.env.GITHUB_CLIENT_ID as string, clientSecret: process.env.GITHUB_CLIENT_SECRET as string, }, }, database: drizzleAdapter(db, { provider: "pg", schema: { ...schema, }, }), user: { additionalFields: { role: { type: "string", required: false, defaultValue: "USER", input: false, // don't allow users to set role }, hasAccess: { type: "boolean", required: false, defaultValue: false, input: false, }, }, changeEmail: { enabled: true, sendChangeEmailVerification: async ({ user, newEmail, url, token }, request) => { await sendChangeEmailVerificationEmail(user.email, url) } } }, }); type Session = typeof auth.$Infer.Session; ``` ### Additional context Package.json versions: - "@polar-sh/sdk": "^0.32.16", - "better-auth": "^1.2.9", - "next": "15.3.3", ### UPDATES - I noticed this error as well on the server "GET /api/auth/customer/portal 500" Unable to find the path, but I can't find the config for that anywhere in better-auth docs. - Someone in a discord group mentioned downgrading to version "@polar-sh/sdk": 0.32.16 , but I am on that version.
GiteaMirror added the nextjs label 2026-03-13 08:38:57 -05:00
Author
Owner

@Adityakk9031 commented on GitHub (Jun 24, 2025):

Is this error in better-auth code ?

@Adityakk9031 commented on GitHub (Jun 24, 2025): Is this error in better-auth code ?
Author
Owner

@indieTrav commented on GitHub (Jun 24, 2025):

Is this error in better-auth code ?

Unsure if its better-auth plugin code or polar. I am using the better-auth plugin polar adapter tho following this documentation: https://www.better-auth.com/docs/plugins/polar#portal-plugin

@indieTrav commented on GitHub (Jun 24, 2025): > Is this error in better-auth code ? Unsure if its better-auth plugin code or polar. I am using the better-auth plugin polar adapter tho following this documentation: https://www.better-auth.com/docs/plugins/polar#portal-plugin
Author
Owner

@indieTrav commented on GitHub (Jun 24, 2025):

Got it fixed: Had to update to latest:

"@polar-sh/better-auth": "^1.0.3",
"@polar-sh/sdk": "^0.34.2",
"better-auth": "^1.2.10",

Thought I was on the latest, but guess not.

@indieTrav commented on GitHub (Jun 24, 2025): Got it fixed: Had to update to latest: "@polar-sh/better-auth": "^1.0.3", "@polar-sh/sdk": "^0.34.2", "better-auth": "^1.2.10", Thought I was on the latest, but guess not.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1415