calcom/cal.diy · error · NotFoundException

Credentials for stripe not found.

Error message

Credentials for stripe not found.

What it means

Thrown by StripeService.validateStripeCredentials when no Stripe credential record exists for the user. It looks up a 'stripe_payment' credential by type and userId; a null/undefined result is rejected as 404 NotFound. This is the 'user has never connected Stripe' state.

Source

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

    );

    return { url: state.returnTo ?? "" };
  }

  async checkIfIndividualStripeAccountConnected(userId: number): Promise<{ status: typeof SUCCESS_STATUS }> {
    const stripeCredentials = await this.credentialsRepository.findCredentialByTypeAndUserId(
      "stripe_payment",
      userId
    );

    return await this.validateStripeCredentials(stripeCredentials);
  }

  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,

View on GitHub (pinned to 176037d0af)

Solutions

  1. Treat a 404 here as 'not connected' and prompt the user to start the Stripe connect flow, rather than showing an error.
  2. Complete the OAuth connect flow via /v2/stripe/redirect to create the stripe_payment credential before validating.
  3. Confirm you are querying with the correct userId and the 'stripe_payment' credential type.
Defensive patterns

Strategy: try-catch

Validate before calling

async function stripeConnectionState(api) {
  try {
    const { status } = await api.validateStripe();
    return status === 'success' ? 'connected' : 'issue';
  } catch (e) {
    if (e.status === 404) return 'not-connected'; // expected for new users
    throw e;
  }
}

Type guard

function isMissingCredentialsError(e: { status: number; message: string }): boolean {
  return e.status === 404 && /Credentials for stripe not found/.test(e.message);
}

Try / catch

try {
  await api.validateStripe();
} catch (e) {
  if (e.status === 404 && /Credentials for stripe not found/.test(e.message)) {
    showConnectStripePrompt(); // not an error - just not connected yet
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the validate/Stripe-status endpoint for a user who has never completed the OAuth connect flow, or whose credential row was deleted, before any stripe_payment credential exists.

Common situations: The UI calls validate on page load for a brand-new user who hasn't connected Stripe yet. A credential was deleted by a disconnect action. The wrong userId is being queried. The credential type slug is wrong.

Related errors


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