RocketChat/Rocket.Chat · error · Meteor.Error
error-unauthorized
error-unauthorized
Error message
Users must have a username
What it means
Thrown by the Hono authentication middleware when a user object is resolved by authenticatedRoute() but the user has no username field (isUserWithUsername returns false). This blocks authenticated-but-usernameless accounts from accessing routes that don't explicitly set userWithoutUsername: true. The check runs after auth/anonymous gating, so the user identity is known — it is the username that is missing.
Source
Thrown at apps/meteor/server/api/v1/middlewares/authenticationHono.ts:42
const user = await api.authenticatedRoute(convertHonoContextToApiActionContext(c, { logger: options.logger }));
const shouldPreventAnonymousRead = !user && options.authOrAnonRequired && !settings.get('Accounts_AllowAnonymousRead');
const shouldPreventUserRead = !user && options.authRequired;
if (shouldPreventAnonymousRead || shouldPreventUserRead) {
const result = api.unauthorized('You must be logged in to do this.');
// TODO: MAJOR
if (!applyBreakingChanges) {
Object.assign(result.body, {
status: 'error',
message: 'You must be logged in to do this.',
});
}
return c.json(result.body, result.statusCode);
}
if (user && !options.userWithoutUsername && !isUserWithUsername(user)) {
throw new Meteor.Error('error-unauthorized', 'Users must have a username');
}
c.set('user', user);
return next();
};
}
View on GitHub (pinned to f9d3ec372b)
Solutions
- Ensure the user account has a username assigned — via admin user management or the user completing their profile setup.
- If the endpoint legitimately serves users without usernames (e.g., method.call routes that already set userWithoutUsername: true), add userWithoutUsername: true to the route's options.
- For OAuth/SAML users, ensure the username mapping is configured in the OAuth/SAML settings.
Example fix
// before (route definition without the flag)
API.v1.get('my-endpoint', { authRequired: true }, action);
// after (allow usernameless users if the endpoint supports it)
API.v1.get('my-endpoint', { authRequired: true, userWithoutUsername: true }, action); Defensive patterns
Strategy: type-guard
Type guard
// Type guard to verify a user object has a username before making API calls
import type { IUser } from '@rocket.chat/core-typings';
function userHasUsername(user: IUser | null | undefined): user is IUser & { username: string } {
return !!user && typeof user.username === 'string' && user.username.length > 0;
}
// Usage before calling an endpoint that requires a username
if (!userHasUsername(currentUser)) {
console.warn('Current user has no username — this endpoint will reject the request.');
} Try / catch
try {
await callApiEndpoint();
} catch (e) {
if (e.error === 'error-unauthorized' && e.reason?.includes('username')) {
console.error('User account has no username. Complete profile setup or contact admin.');
return;
}
throw e;
} Prevention
- Ensure all user accounts (including OAuth/SAML/bots) have a username assigned during provisioning.
- For routes that legitimately serve usernameless users, set userWithoutUsername: true in route options.
- Run a periodic audit query to find users with null/undefined usernames.
When it happens
Trigger: An authenticated request where the user account exists and is valid but the username property is undefined. This can happen with certain OAuth/SAML accounts that did not complete username assignment, bot accounts created without a username, or users in a partially-migrated state.
Common situations: OAuth provider (Google, GitHub, etc.) returned no username and the account registration flow was interrupted; a bot or integration token was created programmatically without setting username; data migration from another platform left some users without usernames; the username was set to null by a cleanup script.
Related errors
- Invalid username
- The username "${user.username}" is already being used. Renam
- Could not open popup
- error-invalid-user
- error-invalid-user
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/64c78c8bb62fabe0.
Report an issue: GitHub.