calcom/cal.diy · error · BadRequestException

Stripe account is not an active account

Error message

Stripe account is not an active account

What it means

Thrown by StripeService.validateStripeCredentials after it retrieves the Stripe account. The comment states both flags must be true for a fully active account; if !payouts_enabled || !charges_enabled, the account is considered not active and the request is rejected as 400 BadRequest. This is a business-level check against the live Stripe account state.

Source

Thrown at apps/api/v2/src/modules/stripe/stripe.service.ts:163

  async validateStripeCredentials(
    credentials?: Credential | null
  ): Promise<{ status: typeof SUCCESS_STATUS }> {
    if (!credentials) {
      throw new NotFoundException("Credentials for stripe not found.");
    }

    if (credentials.invalid) {
      throw new BadRequestException("Invalid stripe credentials.");
    }

    const stripeKey = JSON.stringify(credentials.key);
    const stripeKeyObject = JSON.parse(stripeKey);

    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",

View on GitHub (pinned to 176037d0af)

Solutions

  1. Direct the user to their Stripe dashboard to complete account verification and resolve any restrictions.
  2. Re-check validate after the user finishes Stripe's onboarding/verification; both flags must be true.
  3. If testing, use a fully-activated Stripe test account rather than a partially-onboarded one.
Defensive patterns

Strategy: try-catch

Validate before calling

async function stripeAccountFullyActive(api) {
  try {
    await api.validateStripe();
    return true;
  } catch (e) {
    if (e.status === 400 && /not an active account/.test(e.message)) return false;
    throw e;
  }
}

Type guard

function isFullyActiveAccount(acct: { payouts_enabled: boolean; charges_enabled: boolean }): boolean {
  return acct.payouts_enabled && acct.charges_enabled;
}

Try / catch

try {
  await api.validateStripe();
} catch (e) {
  if (e.status === 400 && /not an active account/.test(e.message)) {
    surfaceToUser('Complete Stripe account verification to accept payments.');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling validate when the connected Stripe account has payouts or charges disabled - e.g. a new account still pending KYC/verification, an account restricted by Stripe, or one where the owner manually disabled payouts/charges.

Common situations: A new Stripe account that hasn't completed identity verification. Stripe restricted the account due to compliance or a dispute. The account is in a region requiring extra setup. The user disabled charges/payouts in Stripe settings.

Related errors


AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12). Data as JSON: /api/errors/2fb1708051df4023. Report an issue: GitHub.