RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-user
error-invalid-user
Error message
Invalid user
What it means
Thrown by addIncomingIntegration when Users.findOneByUsername(integration.username) returns null: no user with that exact username exists in this workspace. Lookup happens before any permission checks on the target user, so a typo fails here rather than as a permission error. Usernames are matched exactly (case-sensitive) against the Users collection.
Source
Thrown at apps/meteor/server/meteor-methods/integrations/incoming/addIncomingIntegration.ts:88
method: 'updateIncomingIntegration',
});
}
}
if (!integration.username || typeof integration.username.valueOf() !== 'string' || integration.username.trim() === '') {
throw new Meteor.Error('error-invalid-username', 'Invalid username', {
method: 'addIncomingIntegration',
});
}
if (integration.script?.trim()) {
validateScriptEngine(integration.scriptEngine ?? 'isolated-vm');
}
const user = await Users.findOneByUsername(integration.username, { projection: { _id: 1 } });
if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'addIncomingIntegration',
});
}
if (!(await hasPermissionAsync(user._id, 'message-impersonate'))) {
throw new Meteor.Error(
'error-user-lacks-message-impersonate-permission',
"User selected for the incoming integration lacks the 'message-impersonate' permission.",
{
method: 'addIncomingIntegration',
},
);
}
// Default to transpiling with Babel for backwards compatibility; integrations
// can opt-out per-record by setting `skipTranspile: true` (removed in 9.0.0).
const skipTranspile = integration.skipTranspile === true;
View on GitHub (pinned to b2c16d5842)
Solutions
- Copy the exact username from Administration -> Users (the @handle, not the display name)
- Create the bot user first (Administration -> Users -> New) and retry with its username
- If provisioning via API, verify with GET /api/v1/users.info?username=... before creating the integration
Example fix
// before
Meteor.callAsync('addIncomingIntegration', { ...integration, username: 'CI Bot' }); // display name -> no such user
// after
Meteor.callAsync('addIncomingIntegration', { ...integration, username: 'ci.bot' }); // exact username from Users admin Defensive patterns
Strategy: validation
Validate before calling
// server-side / REST caller: confirm the user exists before the DDP/method call
const res = await fetch(`${root}/api/v1/users.info?username=${encodeURIComponent(integration.username)}`, { headers: authHeaders });
if (!res.ok) throw new Error(`post-as user '${integration.username}' does not exist`);
await Meteor.callAsync('addIncomingIntegration', integration); Type guard
const isUsernameOfExistingUser = (username: string, known: { username: string }[]) => known.some((u) => u.username === username); Try / catch
try {
await Meteor.callAsync('addIncomingIntegration', integration);
} catch (err) {
if (err instanceof Meteor.Error && err.error === 'error-invalid-user') { /* surface 'user not found', offer user picker */ }
} Prevention
- Use a user picker fed by the live directory rather than typed names
- Provision the bot user before the integration in setup scripts
- Re-verify hard-coded usernames when promoting between environments
When it happens
Trigger: username: 'CI Bot' (display name instead of username), 'john.doe' after the user renamed to 'john.doe2', a user deleted from the workspace, or the account existing only on a different server/deployment.
Common situations: Copy-pasting the visible name from the UI instead of the @username; hard-coded bot username that was never provisioned on this environment; multi-environment configs where the bot exists in staging but not production.
Related errors
- error-invalid-post-as-user
- error-invalid-channel
- error-invalid-channel-start-with-chars
- error-invalid-username
- error-user-lacks-message-impersonate-permission
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/bb3c0507726dc02d.
Report an issue: GitHub.