{"record":{"id":"c068705fc7ab6500","repo":"FlowiseAI/Flowise","slug":"unauthorized","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"exception","errorClass":"InternalFlowiseError","httpStatus":401,"severity":"error","filePath":"packages/server/src/IdentityManager.ts","lineNumber":395,"sourceCode":"    }\n\n    public async getPlanProration(subscriptionId: string, newPlanId: string) {\n        if (!subscriptionId || !newPlanId) return {}\n\n        if (!this.stripeManager) {\n            throw new Error('Stripe manager is not initialized')\n        }\n        return await this.stripeManager.getPlanProration(subscriptionId, newPlanId)\n    }\n\n    public async updateSubscriptionPlan(req: Request, subscriptionId: string, newPlanId: string, prorationDate: number) {\n        if (!subscriptionId || !newPlanId) return {}\n\n        if (!this.stripeManager) {\n            throw new Error('Stripe manager is not initialized')\n        }\n        if (!req.user) {\n            throw new InternalFlowiseError(StatusCodes.UNAUTHORIZED, GeneralErrorMessage.UNAUTHORIZED)\n        }\n        const { success, subscription } = await this.stripeManager.updateSubscriptionPlan(subscriptionId, newPlanId, prorationDate)\n        if (success) {\n            // Fetch product details to get quotas\n            const product = await this.stripeManager.getStripe().products.retrieve(newPlanId)\n            const productMetadata = product.metadata\n\n            // Extract quotas from metadata\n            const quotas: Record<string, number> = {}\n            for (const key in productMetadata) {\n                if (key.startsWith('quota:')) {\n                    quotas[key] = parseInt(productMetadata[key])\n                }\n            }\n\n            const additionalSeatsItem = subscription.items.data.find(\n                (item) => (item.price.product as string) === process.env.ADDITIONAL_SEAT_ID\n            )","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/server/src/IdentityManager.ts#L377-L413","documentation":"Thrown by IdentityManager.updateSubscriptionPlan() as an InternalFlowiseError with HTTP 401 when req.user is falsy. The method mutates subscription and then writes into req.user and req.session.passport.user, so it requires an authenticated passport session. If the route did not attach req.user (auth middleware missing or failed), the method refuses to proceed. Unlike the plain Error throws around it, this is a typed InternalFlowiseError carrying the UNAUTHORIZED general message.","triggerScenarios":"Calling updateSubscriptionPlan on a request that bypassed or failed authentication; an auth middleware ordering bug where the route runs before passport.session()/authenticate; an expired session where req.user was cleared; a programmatic/internal call that did not synthesize a user on the request.","commonSituations":"A route registered without the auth middleware; session expired mid-flow; a refactor that reordered middleware; a direct service-layer call from a job that has no request context.","solutions":["Ensure the route is behind the auth middleware (e.g. app.use(authenticate) before the plan-change handler).","Check req.isAuthenticated()/req.user at the controller and return 401 before delegating to IdentityManager.","If calling from a non-request context, construct a synthetic Request with a valid user or refactor the user-dependent logic out of this method."],"exampleFix":"// before\nconst result = await identityManager.updateSubscriptionPlan(req, subId, newPlanId, prorationDate) // req.user may be undefined\n\n// after\nif (!req.user) {\n    return res.status(401).json({ message: 'Authentication required' })\n}\nconst result = await identityManager.updateSubscriptionPlan(req, subId, newPlanId, prorationDate)","handlingStrategy":"validation","validationCode":"if (!req.user) {\n    return res.status(401).json({ message: 'Authentication required' })\n}\nconst result = await identityManager.updateSubscriptionPlan(req, subId, newPlanId, prorationDate)","typeGuard":"const hasAuthenticatedUser = (req: Request): req is Request & { user: LoggedInUser } =>\n    Boolean(req.user)","tryCatchPattern":"try {\n    const result = await identityManager.updateSubscriptionPlan(req, subId, newPlanId, prorationDate)\n} catch (e) {\n    if (e instanceof InternalFlowiseError && e.statusCode === StatusCodes.UNAUTHORIZED) {\n        return res.status(401).json({ message: 'Authentication required' })\n    }\n    throw e\n}","preventionTips":["Put the plan-change route behind the auth middleware (passport session).","Check req.isAuthenticated()/req.user at the controller boundary.","Keep middleware ordering stable across refactors."],"tags":["authentication","authorization","session","passport","http-401"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}