RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-username
error-invalid-username
Error message
Invalid username
What it means
Thrown by addIncomingIntegration when integration.username is missing, not a string, or trims to empty. This username is the 'post as' identity: every message delivered by the incoming webhook is attributed to this user, so it is mandatory even when a script is provided. check() at the top of the method already requires username: String, so in practice this fires for whitespace-only values or when the exported helper is called directly with an incomplete object.
Source
Thrown at apps/meteor/server/meteor-methods/integrations/incoming/addIncomingIntegration.ts:76
if (integration.channel.trim() === '') {
throw new Meteor.Error('error-invalid-channel', 'Invalid channel', {
method: 'addIncomingIntegration',
});
}
const channels = integration.channel.split(',').map((channel) => channel.trim());
for (const channel of channels) {
if (!validChannelChars.includes(channel[0])) {
throw new Meteor.Error('error-invalid-channel-start-with-chars', 'Invalid channel. Start with @ or #', {
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(View on GitHub (pinned to b2c16d5842)
Solutions
- Set username to the exact username string of an existing workspace user, e.g. a dedicated bot account
- Trim and require a non-empty username in the client form before calling
- Migrate to POST /api/v1/integrations.create which validates the same field (removed method in 9.0.0)
Example fix
// before
Meteor.callAsync('addIncomingIntegration', { ...integration, username: ' ' });
// after
Meteor.callAsync('addIncomingIntegration', { ...integration, username: 'ci-bot' }); // existing workspace user Defensive patterns
Strategy: validation
Validate before calling
if (typeof integration.username !== 'string' || integration.username.trim() === '') throw new Error('post-as username is required');
await Meteor.callAsync('addIncomingIntegration', integration); Type guard
const isNonBlankUsername = (u: unknown): u is string => typeof u === 'string' && u.trim() !== '';
Try / catch
try {
await Meteor.callAsync('addIncomingIntegration', integration);
} catch (err) {
if (err instanceof Meteor.Error && err.error === 'error-invalid-username') { /* require username field */ }
} Prevention
- Make the post-as user a required dropdown of existing users instead of free text
- Trim before submit
- Default to a known bot account in provisioning scripts
When it happens
Trigger: Calling addIncomingIntegration with username: ' ' or omitting username when invoking the exported server function directly (bypassing the method wrapper's type definitions).
Common situations: Form submits before the 'Post as' field is chosen; payload assembled conditionally and username key skipped; automation scripts that assume the server defaults the username (it does not).
Related errors
- error-invalid-channel
- error-invalid-channel-start-with-chars
- error-invalid-user
- error-user-lacks-message-impersonate-permission
- error-invalid-room
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/ecb071afe5c0e35d.
Report an issue: GitHub.