RocketChat/Rocket.Chat · error · Error
Username is required
Error message
Username is required
What it means
Client-side guard in the UsersInRole admin panel: when removing a user from a role, the handler receives the row's username and throws a plain Error 'Username is required' if it is falsy before calling POST /v1/roles.removeUserFromRole. The caught error is shown as a toast. It signals a UI/data defect — a role-membership row without a username — rather than a server problem.
Source
Thrown at apps/meteor/client/views/admin/permissions/UsersInRole/hooks/useRemoveUserFromRole.tsx:30
roleDescription,
}: {
rid?: IRoom['_id'];
roleId: IRole['_id'];
roleName: IRole['name'];
roleDescription: IRole['description'];
}) => {
const { t } = useTranslation();
const setModal = useSetModal();
const dispatchToastMessage = useToastMessageDispatch();
const queryClient = useQueryClient();
const removeUserFromRoleEndpoint = useEndpoint('POST', '/v1/roles.removeUserFromRole');
const handleRemove = useStableCallback((username: IUserInRole['username']) => {
const remove = async () => {
try {
if (!username) throw new Error('Username is required');
await removeUserFromRoleEndpoint({ roleId, username, scope: rid });
dispatchToastMessage({ type: 'success', message: t('User_removed') });
queryClient.invalidateQueries({
queryKey: ['getUsersInRole'],
});
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
} finally {
setModal(null);
}
};
setModal(
<GenericModal variant='danger' onConfirm={remove} onCancel={() => setModal(null)} confirmText={t('Delete')}>
{t('The_user_s_will_be_removed_from_role_s', { username, role: roleDescription || roleName })}
</GenericModal>,
);View on GitHub (pinned to b2c16d5842)
Solutions
- Inspect the getUsersInRole response for the offending row and fix the underlying data so username is present.
- Verify the component passes username (not name/userId) into handleRemove.
- If memberships without usernames are legitimate in your deployment, guard the UI earlier and hide the remove action for such rows.
Example fix
// before
if (!username) throw new Error('Username is required');
// after: prevent the broken row from offering 'remove'
const canRemove = Boolean(row.username);
<Table.Cell>{canRemove ? <RemoveButton username={row.username} /> : null}</Table.Cell> Defensive patterns
Strategy: type-guard
Validate before calling
const rows = (await getUsersInRole({ roleId })).users;
const removable = rows.filter((r) => Boolean(r.username)); Type guard
const hasUsername = (row: IUserInRole): row is IUserInRole & { username: string } =>
typeof row.username === 'string' && row.username.length > 0; Try / catch
try { await handleRemove(row.username); } catch (e) { if ((e as Error).message === 'Username is required') { /* fix the row data, then retry */ return; } throw e; } Prevention
- Validate API payloads include username before rendering action buttons.
- Hide destructive actions for rows missing required identity fields.
- Add schema validation on the getUsersInRole response in dev builds.
When it happens
Trigger: Clicking 'remove' on a users-in-role table row whose username field is empty/undefined (data fetched from GET /v1/roles.getUsersInRole lacking username), or a programmatic call of handleRemove with no argument.
Common situations: Broken/incomplete REST payload for users-in-role (custom fields stripping username); corrupted membership documents; regressions in the table component passing the wrong property.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- error-invalid-role
- error-permission-not-found
- error-action-not-allowed
- error-action-not-allowed
- not_authorized
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/295790eb79541317.
Report an issue: GitHub.