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
- Direct the user to their Stripe dashboard to complete account verification and resolve any restrictions.
- Re-check validate after the user finishes Stripe's onboarding/verification; both flags must be true.
- 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
- Guide users through full Stripe onboarding (KYC, bank account) before relying on payments.
- Re-validate after users finish Stripe verification rather than assuming instant activation.
- Use a fully-activated Stripe test account in non-production environments.
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
- Missing `state` query param
- error=${error}&error_description=${error_description}
- Invalid Access token.
- Stripe app not found
- Invalid Access token.
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/2fb1708051df4023.
Report an issue: GitHub.