calcom/cal.diy · error · BadRequestException
Failed to create a customer on Stripe.
Error message
Failed to create a customer on Stripe.
What it means
Thrown by StripeService.generateTeamCheckoutSession when getStripeCustomerIdFromUserId returns null for the team owner. That helper returns null if the user has no email or if no Stripe customer id can be obtained; the session cannot be created without a customer, so the request is rejected as 400 BadRequest.
Source
Thrown at apps/api/v2/src/modules/stripe/stripe.service.ts:176
const stripeAccount = await stripeInstance.accounts.retrieve(stripeKeyObject?.stripe_user_id);
// both of these should be true for an account to be fully active
if (!stripeAccount.payouts_enabled || !stripeAccount.charges_enabled) {
throw new BadRequestException("Stripe account is not an active account");
}
return {
status: SUCCESS_STATUS,
};
}
async generateTeamCheckoutSession(pendingPaymentTeamId: number, ownerId: number) {
const stripe = this.getStripe();
const customer = await this.getStripeCustomerIdFromUserId(ownerId);
if (!customer) {
throw new BadRequestException("Failed to create a customer on Stripe.");
}
const session = await stripe.checkout.sessions.create({
customer,
mode: "subscription",
allow_promotion_codes: true,
success_url: `${this.webAppUrl}/api/teams/api/create?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${this.webAppUrl}/settings/my-account/profile`,
line_items: [
{
/** We only need to set the base price and we can upsell it directly on Stripe's checkout */
price: this.teamMonthlyPriceId,
/**Initially it will be just the team owner */
quantity: 1,
},
],
customer_update: {
address: "auto",View on GitHub (pinned to 176037d0af)
Solutions
- Ensure the team owner has a valid email on their user profile before starting checkout.
- Verify Stripe keys are configured and reachable so customer creation succeeds.
- Retry checkout; if it persists, inspect server logs for the upstream customer-creation failure.
Defensive patterns
Strategy: try-catch
Validate before calling
async function ensureOwnerReadyForCheckout(api, ownerId: number) {
const user = await api.getUser(ownerId);
if (!user?.email) throw new Error('Team owner needs a verified email before checkout');
} Type guard
function ownerHasEmail(user: { email?: string | null } | null): boolean {
return !!user?.email;
} Try / catch
try {
const { url } = await api.generateTeamCheckoutSession(teamId, ownerId);
window.location.href = url;
} catch (e) {
if (e.status === 400 && /Failed to create a customer/.test(e.message)) {
surfaceToUser('We could not start checkout. Confirm your email and try again.');
} else throw e;
} Prevention
- Ensure the team owner has a valid email on their profile before enabling checkout.
- Verify Stripe keys are configured and Stripe is reachable so customer creation succeeds.
- Log the underlying customer-creation failure server-side to distinguish no-email vs Stripe error.
When it happens
Trigger: Initiating a team checkout (e.g. upgrading/creating a team) for an owner whose user record has no email, or for whom Stripe customer creation/lookup failed upstream, so getStripeCustomerIdFromUserId resolves to null.
Common situations: The owner's account has no verified email. Stripe customer creation failed earlier due to bad keys or a network error and the null propagated. The user was created via an SSO/invite flow that left email blank. Stripe is misconfigured in this environment.
Related errors
- Failed generating a Stripe checkout session URL.
- Missing `state` query param
- error=${error}&error_description=${error_description}
- Invalid Access token.
- Stripe app not found
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/d447b9b89a0df856.
Report an issue: GitHub.