{"record":{"id":"4556d12742bc647a","repo":"HeyPuter/puter","slug":"internal-error-4556d1","errorCode":"internal_error","errorMessage":"user-protected state missing","messagePattern":"user-protected state missing","errorType":"exception","errorClass":"HttpError","httpStatus":500,"severity":"critical","filePath":"src/backend/core/http/middleware/userProtected.ts","lineNumber":200,"sourceCode":"\n    // 3. Password (bcrypt) OR valid OIDC revalidation cookie.\n    //\n    //   - Temp users (no password + no email) pass only when the route was\n    //     registered with `allowTempUsers: true` (delete-own-user).\n    //   - `req.body.password` → bcrypt match against user row. OIDC-only\n    //     accounts bounce with `oidc_revalidation_required` + a\n    //     `revalidate_url` helper so the GUI can open the OIDC popup.\n    //   - Otherwise accept a valid `puter_revalidation` cookie. Expiry,\n    //     `purpose === 'revalidate'`, matching `user_uuid` all required.\n    //   - Password account, neither credential → 403 `password_required`.\n    const verifyIdentity: RequestHandler = async (\n        req: Request,\n        _res: Response,\n        next: NextFunction,\n    ) => {\n        const user = req.userProtected?.user;\n        if (!user)\n            throw new HttpError(500, 'user-protected state missing', {\n                legacyCode: 'internal_error',\n            });\n\n        const isTemp = user.password === null && user.email === null;\n        if (isTemp) {\n            if (allowTemp) return next();\n            throw new HttpError(403, 'Temporary account', {\n                legacyCode: 'temporary_account',\n            });\n        }\n\n        const bodyPassword =\n            typeof req.body?.password === 'string' ? req.body.password : null;\n        if (bodyPassword) {\n            if (user.password === null) {\n                const fields = await buildRevalidateFields(\n                    config,\n                    oidcService,","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/core/http/middleware/userProtected.ts#L182-L218","documentation":"HTTP 500 raised in the `verifyIdentity` step of userProtected when `req.userProtected.user` is unset. That value is populated exclusively by the preceding `refreshUser` middleware, so a 500 here means the gate array was mis-wired: verifyIdentity ran without refreshUser, or someone selected a subset of the returned array. This is an internal backend bug, never a legitimate client error.","triggerScenarios":"A route registered only the verifyIdentity handler (or reordered the array) instead of the full `[requireSessionCookie, refreshUser, verifyIdentity]` from `createUserProtectedGate`; a custom wiring that skipped refreshUser.","commonSituations":"Refactor that picked middleware subsets; copy-paste route registration that omitted refreshUser; someone reordered the chain.","solutions":["Register the entire array returned by createUserProtectedGate — do not pick subsets.","Ensure refreshUser runs before verifyIdentity (it sets req.userProtected).","If using a custom chain, add the refreshUser step that populates req.userProtected.user.","Report as a backend bug if the array is intact."],"exampleFix":"// before\napp.delete('/user', verifyIdentity, handler); // missing refreshUser\n// after\nconst gate = createUserProtectedGate(deps, { allowTempUsers: true });\napp.delete('/user', ...gate, handler); // full chain","handlingStrategy":"validation","validationCode":"// Server-side: assert the gate array is intact before registering:\nconst gate = createUserProtectedGate(deps, opts);\nif (gate.length < 3) throw new Error('userProtected gate must include refreshUser');\napp.delete('/user', ...gate, handler);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always register the full array returned by createUserProtectedGate.","Never select a subset (e.g. verifyIdentity alone).","In review, confirm refreshUser precedes verifyIdentity."],"tags":["internal","bug","middleware","user-protected","misconfiguration"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}