danny-avila/LibreChat · error · Error
User does not exist
Error message
User does not exist
What it means
Thrown only on the ADMIN OpenID path. The regular `'openid'` strategy is created with `createOpenIDCallback()` (existingUsersOnly falsy) and will auto-create unknown users; the `'openidAdmin'` strategy is created with `createOpenIDCallback(true)`, so when `findOpenIDUser` resolves no matching user, this guard throws before the create-user branch. Crucially, `'User does not exist'` is NOT in the callback's special-case list (which covers only domain/`AUTH_FAILED`/role messages), so it becomes `done(err)` — a hard Passport error that the authenticator routes to Express's error handler as a 500 rather than the friendly `auth_failed` redirect.
Source
Thrown at api/strategies/openidStrategy.js:683
const rolesList =
requiredRoles.length === 1
? `"${requiredRoles[0]}"`
: `one of: ${requiredRoles.map((r) => `"${r}"`).join(', ')}`;
throw new Error(`You must have ${rolesList} role to log in.`);
}
}
let username = '';
if (process.env.OPENID_USERNAME_CLAIM) {
username = userinfo[process.env.OPENID_USERNAME_CLAIM];
} else {
username = convertToUsername(
userinfo.preferred_username || userinfo.username || userinfo.email,
);
}
if (existingUsersOnly && !user) {
throw new Error('User does not exist');
}
if (!user) {
user = {
provider: 'openid',
openidId: userinfo.sub,
username,
email: email || '',
emailVerified: userinfo.email_verified || false,
name: fullName,
idOnTheSource: userinfo.oid,
openidIssuer,
};
const balanceConfig = getBalanceConfig(appConfig);
user = await createUser(user, balanceConfig, true, true);
} else {
user.provider = 'openid';View on GitHub (pinned to 5ff282f900)
Solutions
- Pre-create the admin user document in the database with the correct `openidId` (token `sub`), `openidIssuer`, and `email` before they attempt admin SSO.
- Confirm the user is hitting the regular user callback (`${APPLE_CALLBACK_URL}`-style `/api/auth/openid/callback`) for normal login, not the admin callback.
- If this surfaces as a 500 and you want a cleaner UX, add `'User does not exist'` to the special-case list in `createOpenIDCallback` so it becomes a `done(null, false, { message })` redirect.
- Verify the user's stored `openidId`/`openidIssuer` still match the current IdP issuer and subject after any IdP migration.
Example fix
// before — admin-only guard throws a message that becomes a 500
if (existingUsersOnly && !user) {
throw new Error('User does not exist');
}
// after — surface as a clean auth failure so the admin sees the login screen, not a 500
if (existingUsersOnly && !user) {
return done(null, false, { message: 'User does not exist' });
} Defensive patterns
Strategy: validation
Validate before calling
// For the admin path, pre-check that a matching user exists before surfacing SSO
async function adminUserExists(findUser, openidId, email) {
return Boolean(await findUser({ $or: [{ openidId }, { email: email?.trim() }] }));
} Type guard
function isAdminCallback(url: string): boolean {
return url.includes('/api/admin/oauth/');
} Try / catch
// Map 'User does not exist' to a clean auth failure instead of a 500
try {
const user = await processOpenIDAuth(tokenset, true);
done(null, user);
} catch (err) {
if (err.message === 'User does not exist') return done(null, false, { message: 'Admin user not provisioned' });
done(err);
} Prevention
- Pre-provision admin user documents with the correct openidId/openidIssuer/email before enabling admin SSO.
- Keep the admin callback URL distinct from the user callback and document that only pre-provisioned admins may use it.
- Consider adding 'User does not exist' to the callback's special-case list so it produces a redirect rather than a 500.
When it happens
Trigger: An administrator navigates to the admin SSO entry point (`/api/admin/oauth/openid/callback`) and authenticates against the IdP, but no user document with a matching `openidId`, `email`, or `openidIssuer` exists in the database yet. This is the intended bootstrap protection: admins must be pre-provisioned.
Common situations: First-time admin SSO setup before any admin user exists in the DB; the admin's IdP subject/email changed so the prior record no longer matches; a non-admin user accidentally using the admin callback URL; test/staging DB reset that wiped user records.
Related errors
- User must be authenticated via OpenID to perform OBO token e
- Email domain not allowed
- auth_failed
- You must have ${rolesList} role to log in.
- Failed to authenticate OAuth tool
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/664324715eb4a693.
Report an issue: GitHub.