{"record":{"id":"d207e1c137fb4d96","repo":"calcom/cal.diy","slug":"credentials-for-stripe-not-found","errorCode":null,"errorMessage":"Credentials for stripe not found.","messagePattern":"Credentials for stripe not found\\.","errorType":"http","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"apps/api/v2/src/modules/stripe/stripe.service.ts","lineNumber":149,"sourceCode":"    );\n\n    return { url: state.returnTo ?? \"\" };\n  }\n\n  async checkIfIndividualStripeAccountConnected(userId: number): Promise<{ status: typeof SUCCESS_STATUS }> {\n    const stripeCredentials = await this.credentialsRepository.findCredentialByTypeAndUserId(\n      \"stripe_payment\",\n      userId\n    );\n\n    return await this.validateStripeCredentials(stripeCredentials);\n  }\n\n  async validateStripeCredentials(\n    credentials?: Credential | null\n  ): Promise<{ status: typeof SUCCESS_STATUS }> {\n    if (!credentials) {\n      throw new NotFoundException(\"Credentials for stripe not found.\");\n    }\n\n    if (credentials.invalid) {\n      throw new BadRequestException(\"Invalid stripe credentials.\");\n    }\n\n    const stripeKey = JSON.stringify(credentials.key);\n    const stripeKeyObject = JSON.parse(stripeKey);\n\n    const stripeAccount = await stripeInstance.accounts.retrieve(stripeKeyObject?.stripe_user_id);\n\n    // both of these should be true for an account to be fully active\n    if (!stripeAccount.payouts_enabled || !stripeAccount.charges_enabled) {\n      throw new BadRequestException(\"Stripe account is not an active account\");\n    }\n\n    return {\n      status: SUCCESS_STATUS,","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/modules/stripe/stripe.service.ts#L131-L167","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Treat a 404 here as 'not connected' and prompt the user to start the Stripe connect flow, rather than showing an error.","Complete the OAuth connect flow via /v2/stripe/redirect to create the stripe_payment credential before validating.","Confirm you are querying with the correct userId and the 'stripe_payment' credential type."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"async function stripeConnectionState(api) {\n  try {\n    const { status } = await api.validateStripe();\n    return status === 'success' ? 'connected' : 'issue';\n  } catch (e) {\n    if (e.status === 404) return 'not-connected'; // expected for new users\n    throw e;\n  }\n}","typeGuard":"function isMissingCredentialsError(e: { status: number; message: string }): boolean {\n  return e.status === 404 && /Credentials for stripe not found/.test(e.message);\n}","tryCatchPattern":"try {\n  await api.validateStripe();\n} catch (e) {\n  if (e.status === 404 && /Credentials for stripe not found/.test(e.message)) {\n    showConnectStripePrompt(); // not an error - just not connected yet\n  } else throw e;\n}","preventionTips":["Treat a 404 from validate as 'not connected' UX, not a hard error.","Complete the Stripe connect flow before showing any payment UI that depends on it.","Query with the correct userId and the 'stripe_payment' credential type."],"tags":["stripe","credentials","not-found","api-v2","onboarding"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}