RocketChat/Rocket.Chat · error · Meteor.Error
error-user-lacks-message-impersonate-permission
error-user-lacks-message-impersonate-permission
Error message
User selected for the incoming integration lacks the 'message-impersonate' permission.
What it means
Thrown by addIncomingIntegration when the 'post as' user resolves but does not hold the 'message-impersonate' permission. The server checks hasPermissionAsync(user._id, 'message-impersonate') on the TARGET user (the one the webhook posts as), not on the caller. This is a security requirement: an incoming webhook sends messages under this user's identity, so impersonation rights are mandatory.
Source
Thrown at apps/meteor/server/meteor-methods/integrations/incoming/addIncomingIntegration.ts:94
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;
const integrationData: IIncomingIntegration = {
...integration,
scriptEngine: integration.scriptEngine ?? 'isolated-vm',
skipTranspile,
type: 'webhook-incoming',
channel: channels,View on GitHub (pinned to b2c16d5842)
Solutions
- Grant 'message-impersonate' to a role held by the target user: Administration -> Permissions -> message-impersonate, tick the bot/custom role
- Or pick a post-as user that already has the permission (e.g. the built-in rocket.cat or a user with admin/bot role that includes it)
- As admin you can also run: Meteor.call('authorization:addPermissionToRole', 'message-impersonate', 'bot') then retry
Example fix
// before: target user's role lacks the permission
Meteor.callAsync('addIncomingIntegration', { ...integration, username: 'intern.user' }); // -> error-user-lacks-message-impersonate-permission
// after: grant the permission to the user's role (Administration -> Permissions -> message-impersonate -> check 'bot'), then
Meteor.callAsync('addIncomingIntegration', { ...integration, username: 'ci-bot' }); // ci-bot has role 'bot' with message-impersonate Defensive patterns
Strategy: try-catch
Try / catch
try {
await Meteor.callAsync('addIncomingIntegration', integration);
} catch (err) {
if (err instanceof Meteor.Error && err.error === 'error-user-lacks-message-impersonate-permission') {
// show 'ask an admin to grant message-impersonate to this user's role' and keep form state
}
} Prevention
- Provision bot roles with message-impersonate included from day one
- Restrict the post-as picker to users whose roles carry message-impersonate
- Document the permission in your integration onboarding runbook
When it happens
Trigger: Choosing a regular employee as the post-as user; creating a bot account whose role lacks message-impersonate; an admin removed message-impersonate from the default bot role as hardening and existing creation flows broke.
Common situations: Fresh workspace where the custom bot role was cloned from User (which lacks the permission); compliance-driven permission lockdowns; integrations built against older Rocket.Chat that did not enforce this check.
Related errors
- not_authorized
- not_authorized
- error-invalid-channel
- error-invalid-channel-start-with-chars
- error-invalid-username
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/9524ac32a8becec4.
Report an issue: GitHub.