{"record":{"id":"e0b80fe026afc745","repo":"Mintplex-Labs/anything-llm","slug":"unauthorized-e0b80f","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":null,"httpStatus":401,"severity":"warning","filePath":"server/endpoints/system.js","lineNumber":617,"sourceCode":"          false,\n          response?.locals?.user?.id\n        );\n        response.status(200).json({ newValues, error });\n      } catch (e) {\n        console.error(e.message, e);\n        response.sendStatus(500).end();\n      }\n    }\n  );\n\n  app.post(\n    \"/system/update-password\",\n    [validatedRequest],\n    async (request, response) => {\n      try {\n        // Cannot update password in multi - user mode.\n        if (multiUserMode(response)) {\n          response.sendStatus(401).end();\n          return;\n        }\n\n        let error = null;\n        const { usePassword, newPassword } = reqBody(request);\n        if (!usePassword) {\n          // Password is being disabled so directly unset everything to bypass validation.\n          process.env.AUTH_TOKEN = \"\";\n          process.env.JWT_SECRET = \"\";\n        } else {\n          // An all-asterisk value is indistinguishable from the UI's masked\n          // placeholder, so updateENV would silently drop it while JWT_SECRET\n          // still rotates - reject it before mutating anything.\n          if (/^\\*+$/.test(String(newPassword))) {\n            response.status(200).json({\n              success: false,\n              error: \"Password cannot consist of only asterisks (*).\",\n            });","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/20f6d3546c1938bfea1ad304f58a592dddcc5948/server/endpoints/system.js#L599-L635","documentation":"This 401 'Unauthorized' from POST /system/update-password (server/endpoints/system.js:615) is an intentional guard, not an exception or an auth failure of your request. The endpoint manages the single shared instance password (AUTH_TOKEN); when multiUserMode(response) is true the instance has per-user accounts, so changing a global password is meaningless and rejected with 401 before any work happens. Password changes in multi-user mode belong to each user's account settings (or admin-driven reset/recovery flows).","triggerScenarios":"Calling POST /api/system/update-password on any instance where multi-user mode was enabled via /system/enable-multi-user; frontend code from an older deployment still invoking the single-user password dialog after migration to multi-user.","commonSituations":"Migrating a single-user instance to multi-user while old UI tabs or scripts remain cached; automation written against the single-user API replayed after enabling multi-user.","solutions":["Use the per-user password flow instead: the user's account settings page, or /system/recover-account + /system/reset-password for recovery","Update/clear cached frontend bundles so the single-user password dialog no longer appears","Treat the 401 as expected behavior - do not retry with different credentials","Only invoke /system/update-password on instances where multi-user mode was never enabled"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const { multiUserMode } = await (\n  await fetch(\"/api/system/multi-user-mode\")\n).json();\nif (multiUserMode) {\n  // do not call /system/update-password - route the user to account settings\n  navigate(\"/settings/account\");\n} else {\n  await updateInstancePassword(newPassword);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Gate the single-user password UI on GET /system/multi-user-mode before showing it","Cache-bust frontend bundles after enabling multi-user mode so stale dialogs disappear","In multi-user mode use account settings or /system/recover-account + /system/reset-password","Treat 401 here as a mode mismatch, never as bad credentials"],"tags":["express","auth","multi-user","password","unauthorized"],"backgroundTag":"multi-user-mode-restriction","analyzedSha":"20f6d3546c1938bfea1ad304f58a592dddcc5948","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}