RocketChat/Rocket.Chat · error · Error
username-required
Error message
username-required
What it means
Thrown by POST /hooks/add/:integrationId/:userId/:token (legacy Zapier-style integration webhook) when event is 'newMessageToUser' but bodyParams.data.username is missing or empty. The outgoing integration needs a @username channel to post into, so creation aborts with the plain error 'username-required'. Note the code checks the '@' prefix before existence, so a missing username always falls through to this throw.
Solutions
- Include data.username (bare username is fine; server prepends '@') in the POST body for newMessageToUser events
- Switch the event to newMessageOnChannel and supply data.channel_name if you meant a channel
- Validate the payload shape before firing the webhook (event-specific required keys)
- Check the integration webhook logs (incomingLogger) to confirm which branch ran
Example fix
// before
await fetch(`${rc}/api/v1/hooks/add/${iid}/${uid}/${tok}`, { method: 'POST', body: JSON.stringify({ event: 'newMessageToUser', name: 'zap', target_url: 'https://cb.example' }) });
// after
await fetch(`${rc}/api/v1/hooks/add/${iid}/${uid}/${tok}`, { method: 'POST', body: JSON.stringify({ event: 'newMessageToUser', name: 'zap', target_url: 'https://cb.example', data: { username: 'jon.doe' } }) }); Defensive patterns
Strategy: validation
Validate before calling
function validateHooksAddPayload(p: {event:string; name:string; target_url:string; data?:{channel_name?:string; username?:string}}) {
if (p.event === 'newMessageToUser' && !p.data?.username) throw new Error('username-required: data.username missing');
if (p.event === 'newMessageOnChannel' && !p.data?.channel_name) throw new Error('channel_name required');
} Type guard
const isMessageToUserPayload = (p: unknown): p is {event:'newMessageToUser'; name:string; target_url:string; data:{username:string}} =>
typeof p === 'object' && p !== null && (p as {event?:string}).event === 'newMessageToUser' && typeof ((p as {data?:{username?:string}}).data)?.username === 'string' && ((p as {data:{username:string}}).data.username.length > 0); Try / catch
try { await postHooksAdd(payload); } catch (e) { if (/username-required/.test(String(e?.message))) { payload.data = { ...payload.data, username: fallbackUser }; await postHooksAdd(payload); } else throw e; } Prevention
- Map required fields per event type before building the payload
- Never send empty-string username (server auto-prefixes '@')
- Reuse the channel template only with newMessageOnChannel
When it happens
Trigger: POST to /api/v1/hooks/add/... with {event:'newMessageToUser', name:'x', target_url:'https://cb'} and no data object; data:{trigger_words:[...]} without username; username:'' (empty string gets auto-prefixed to '@' and behaves unexpectedly — always send a real username).
Common situations: Zapier-style flows copied from the channel template (newMessageOnChannel uses channel_name) without swapping to username; form integrations with optional username left blank; version drift in a fields mapper dropping the username key.
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-channel-start-with-chars
- error-invalid-event-type
- error-invalid-targetRoom
- error-invalid-token
- error-invalid-triggerWords
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/d9a4a734045e3607.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/webhooks.ts:86
urls: [options.target_url],
name: options.name,
channel: options.data.channel_name,
triggerWords: options.data.trigger_words,
type: 'webhook-outgoing',
event: 'sendMessage',
token: Random.id(24),
scriptEnabled: false,
script: '',
enabled: true,
_id: Random.id(),
_updatedAt: new Date(),
});
case 'newMessageToUser':
if (options.data?.username?.indexOf('@') === -1) {
options.data.username = `@${options.data.username}`;
}
if (!options.data?.username) {
throw new Error('username-required');
}
return addOutgoingIntegration(user._id, {
username: 'rocket.cat',
urls: [options.target_url],
name: options.name,
channel: options.data.username,
triggerWords: options.data.trigger_words,
_id: '',
type: 'webhook-outgoing',
token: '',
scriptEnabled: false,
script: '',
enabled: false,
_updatedAt: new Date(),
event: 'sendMessage',
});
}View on GitHub (pinned to b2c16d5842)