{"record":{"id":"daf2dcd866d8a942","repo":"FlowiseAI/Flowise","slug":"subscription-id-is-required","errorCode":null,"errorMessage":"Subscription ID is required","messagePattern":"Subscription ID is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/StripeManager.ts","lineNumber":134,"sourceCode":"            subsriptionDetails: this.getSubscriptionObject(subscription)\n        })\n\n        return features\n    }\n\n    public async createStripeCustomerPortalSession(req: Request) {\n        if (!this.stripe) {\n            throw new Error('Stripe is not initialized')\n        }\n\n        const customerId = req.user?.activeOrganizationCustomerId\n        if (!customerId) {\n            throw new Error('Customer ID is required')\n        }\n\n        const subscriptionId = req.user?.activeOrganizationSubscriptionId\n        if (!subscriptionId) {\n            throw new Error('Subscription ID is required')\n        }\n\n        try {\n            const prodPriceIds = await this.getPriceIds()\n            const configuration = await this.createPortalConfiguration(prodPriceIds)\n\n            const portalSession = await this.stripe.billingPortal.sessions.create({\n                customer: customerId,\n                configuration: configuration.id,\n                return_url: `${process.env.APP_URL}/account`\n                /* We can't have flow_data because it does not support multiple subscription items\n                flow_data: {\n                    type: 'subscription_update',\n                    subscription_update: {\n                        subscription: subscriptionId\n                    },\n                    after_completion: {\n                        type: 'redirect',","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/server/src/StripeManager.ts#L116-L152","documentation":"Immediately after the customer-ID check in createStripeCustomerPortalSession, the code reads req.user.activeOrganizationSubscriptionId and throws a generic Error if it's falsy. The portal configuration and session creation both need a subscription context, so a missing subscription ID is a hard precondition. This fires for org customers who exist in Stripe but have no subscription tied to the active organization.","triggerScenarios":"An authenticated user with a Stripe customer record but no subscription on their active organization calls the portal-session endpoint. Also when activeOrganizationSubscriptionId isn't set by the auth middleware despite a subscription existing.","commonSituations":"Customer created during signup but checkout/subscription step abandoned. Org has a customer ID persisted but the subscription ID field was never written back after checkout. Middleware/auth desync after subscription cancellation removed the ID.","solutions":["Confirm the active organization completed subscription checkout so activeOrganizationSubscriptionId is persisted on the user/org.","Check the auth middleware persists the subscription ID alongside the customer ID after a successful checkout webhook.","On the client, gate the portal action on subscription presence (not just customer presence).","If the subscription was canceled and the ID cleared, route the user to re-subscribe rather than the portal."],"exampleFix":"// before\nconst subscriptionId = req.user?.activeOrganizationSubscriptionId\nif (!subscriptionId) {\n    throw new Error('Subscription ID is required')\n}\n\n// after\nif (!subscriptionId) {\n    throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, 'Active organization has no subscription. Start a subscription first.')\n}","handlingStrategy":"validation","validationCode":"function requireOrgSubscription(user: unknown): asserts user is { activeOrganizationSubscriptionId: string } {\n    const u = user as any\n    if (!u?.activeOrganizationSubscriptionId) {\n        throw new Error('Active organization has no subscription. Start a subscription first.')\n    }\n}\nrequireOrgSubscription(req.user)","typeGuard":"function hasOrgSubscriptionId(user: unknown): user is { activeOrganizationSubscriptionId: string } {\n    return typeof (user as any)?.activeOrganizationSubscriptionId === 'string' && (user as any).activeOrganizationSubscriptionId.length > 0\n}","tryCatchPattern":"try {\n    const session = await stripeManager.createStripeCustomerPortalSession(req)\n} catch (err) {\n    if (err instanceof Error && err.message === 'Subscription ID is required') {\n        return res.status(StatusCodes.BAD_REQUEST).json({ error: 'No active subscription for this organization' })\n    }\n    throw err\n}","preventionTips":["Persist the subscription ID on the org record via the checkout-completed webhook.","Verify the auth middleware reads the subscription ID into req.user.","Gate the portal action on subscription presence, not just customer presence.","After cancellation, route users to re-subscribe instead of the portal."],"tags":["stripe","billing","billing-portal","subscription","validation"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}