{"record":{"id":"4501f76c5c057c38","repo":"langfuse/langfuse","slug":"internal-server-error-4501f7","errorCode":"INTERNAL_SERVER_ERROR","errorMessage":"Organization not found","messagePattern":"Organization not found","errorType":"exception","errorClass":"TRPCError","httpStatus":500,"severity":"error","filePath":"web/src/ee/features/billing/server/resolveBillingService.ts","lineNumber":49,"sourceCode":" * never a half-configured CHB flow. Orgs already carrying CHB state cannot be\n * served by Stripe and error instead.\n *\n * This dispatch is also the structural interlock that keeps Stripe checkout\n * unreachable for any org holding a `cloudConfig.clickhouse` block: such\n * orgs always resolve to the CHB service.\n */\nexport const resolveBillingService = async (\n  ctx: OrgAuthedContext,\n  orgId: string,\n): Promise<{\n  billingProvider: BillingProvider;\n  service: CloudBillingService;\n}> => {\n  const org = await ctx.prisma.organization.findUnique({\n    where: { id: orgId },\n  });\n  if (!org) {\n    throw new TRPCError({\n      code: \"INTERNAL_SERVER_ERROR\",\n      message: \"Organization not found\",\n    });\n  }\n  const parsedOrg = parseDbOrg(org);\n  // The cutoff is injected rather than read inside the resolver: the shared\n  // module is exported from the client-safe barrel, so web passes the value from\n  // its own validated env schema.\n  const cutoff = env.LANGFUSE_CLOUD_BILLING_CHB_CUTOFF_DATE;\n  const billingProvider = getBillingProvider(parsedOrg, { cutoff });\n\n  if (billingProvider === \"clickhouse\") {\n    // Shared process-wide, so every billing request reuses one Auth0 token\n    // cache rather than minting a token per request.\n    const client = getChbApiClient();\n    if (!client) {\n      if (parsedOrg.cloudConfig?.clickhouse?.organizationId) {\n        // Sticky CHB org: Stripe cannot serve it, this is a config error","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/langfuse/langfuse/blob/59d92c7cf365150d10b753b5a0d1708902a2ed60/web/src/ee/features/billing/server/resolveBillingService.ts#L31-L67","documentation":"resolveBillingService loads the organization from Postgres to decide which billing backend (Stripe vs ClickHouse Billing) serves it; if findUnique returns null it throws INTERNAL_SERVER_ERROR 'Organization not found'. The orgId came from a caller that assumed the org exists, so this signals stale or forged input rather than a billing problem.","triggerScenarios":"Passing an orgId to resolveBillingService (transitively any billing service method) for an organization that was deleted, or a typo'd/mismatched org id (e.g. project id passed as orgId).","commonSituations":"Org deleted while a user had a billing page open; race between org deletion and in-flight requests; tests using fixture ids that were never created.","solutions":["Verify the orgId is a real organization id from the same tenant/session before calling billing APIs.","Handle org-deletion races upstream by invalidating sessions/caching when an org is removed.","Consider NOT_FOUND semantics: this is arguably a 404 and callers should treat missing-org as expected, not a 500."],"exampleFix":"// before\nconst svc = await resolveBillingService(ctx, maybeStaleOrgId);\n// after\nconst org = await ctx.prisma.organization.findUnique({ where: { id: orgId } });\nif (!org) throw new TRPCError({ code: \"NOT_FOUND\", message: \"Organization not found\" });\nconst svc = await resolveBillingService(ctx, orgId);","handlingStrategy":"validation","validationCode":"const org = await ctx.prisma.organization.findUnique({\n  where: { id: orgId, members: { some: { userId: session.user.id } } },\n});\nif (!org) throw new TRPCError({ code: \"NOT_FOUND\" });","typeGuard":null,"tryCatchPattern":"catch (e) { if (e instanceof TRPCError && e.code === \"INTERNAL_SERVER_ERROR\" && e.message === \"Organization not found\") { /* treat as stale org, refresh session */ } throw e; }","preventionTips":["Derive orgId from the authenticated session rather than client input.","Invalidate sessions and caches on org deletion."],"tags":["billing","not-found","prisma","organization"],"backgroundTag":"entity-not-found","analyzedSha":"59d92c7cf365150d10b753b5a0d1708902a2ed60","analyzedAt":"2026-08-27T22:22:00.402Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}