FlowiseAI/Flowise · error · InternalFlowiseError

Unauthorized

Error message

Unauthorized

What it means

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.

Source

Thrown at packages/server/src/IdentityManager.ts:395

    }

    public async getPlanProration(subscriptionId: string, newPlanId: string) {
        if (!subscriptionId || !newPlanId) return {}

        if (!this.stripeManager) {
            throw new Error('Stripe manager is not initialized')
        }
        return await this.stripeManager.getPlanProration(subscriptionId, newPlanId)
    }

    public async updateSubscriptionPlan(req: Request, subscriptionId: string, newPlanId: string, prorationDate: number) {
        if (!subscriptionId || !newPlanId) return {}

        if (!this.stripeManager) {
            throw new Error('Stripe manager is not initialized')
        }
        if (!req.user) {
            throw new InternalFlowiseError(StatusCodes.UNAUTHORIZED, GeneralErrorMessage.UNAUTHORIZED)
        }
        const { success, subscription } = await this.stripeManager.updateSubscriptionPlan(subscriptionId, newPlanId, prorationDate)
        if (success) {
            // Fetch product details to get quotas
            const product = await this.stripeManager.getStripe().products.retrieve(newPlanId)
            const productMetadata = product.metadata

            // Extract quotas from metadata
            const quotas: Record<string, number> = {}
            for (const key in productMetadata) {
                if (key.startsWith('quota:')) {
                    quotas[key] = parseInt(productMetadata[key])
                }
            }

            const additionalSeatsItem = subscription.items.data.find(
                (item) => (item.price.product as string) === process.env.ADDITIONAL_SEAT_ID
            )

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Ensure the route is behind the auth middleware (e.g. app.use(authenticate) before the plan-change handler).
  2. Check req.isAuthenticated()/req.user at the controller and return 401 before delegating to IdentityManager.
  3. 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.

Example fix

// before
const result = await identityManager.updateSubscriptionPlan(req, subId, newPlanId, prorationDate) // req.user may be undefined

// after
if (!req.user) {
    return res.status(401).json({ message: 'Authentication required' })
}
const result = await identityManager.updateSubscriptionPlan(req, subId, newPlanId, prorationDate)
Defensive patterns

Strategy: validation

Validate before calling

if (!req.user) {
    return res.status(401).json({ message: 'Authentication required' })
}
const result = await identityManager.updateSubscriptionPlan(req, subId, newPlanId, prorationDate)

Type guard

const hasAuthenticatedUser = (req: Request): req is Request & { user: LoggedInUser } =>
    Boolean(req.user)

Try / catch

try {
    const result = await identityManager.updateSubscriptionPlan(req, subId, newPlanId, prorationDate)
} catch (e) {
    if (e instanceof InternalFlowiseError && e.statusCode === StatusCodes.UNAUTHORIZED) {
        return res.status(401).json({ message: 'Authentication required' })
    }
    throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/c068705fc7ab6500. Report an issue: GitHub.