RocketChat/Rocket.Chat · error · Error
error-livechat-visitor-registration
Error message
error-livechat-visitor-registration
What it means
Thrown by POST /api/v1/livechat/messages (note: authRequired — an agent/user token, unlike the visitor routes) when the supplied visitor.token does not match an existing visitor and the fallback attempt to create one fails: registerGuest() from @rocket.chat/omni-core returned null. registerGuest nulls out when the visitor payload is invalid — e.g. missing required fields, unparseable visitor data, or a department that cannot be resolved/served.
Solutions
- Send a minimal but well-formed visitor object (token, name) and confirm it registers via POST /api/v1/livechat/visitor first, then reuse that token in livechat/messages.
- If passing department, use an enabled department id from GET /api/v1/livechat/departments and provide valid email arrays.
- Check server logs — registerGuest failures around registration (department resolution, validation) are logged and pinpoint the offending field.
- Ensure the request carries a valid user auth token (X-Auth-Token/X-User-Id), since this route is not visitor-authenticated.
Example fix
// before (malformed visitor payload)
await sdk.post('livechat/messages', {
visitor: { token: 'tkn1', department: 'retired-dept-id' },
messages: [{ msg: 'hello' }],
});
// after (pre-register a valid visitor, then send messages)
await sdk.post('livechat/visitor', { visitor: { token: 'tkn1', name: 'Lead' } });
await sdk.post('livechat/messages', {
visitor: { token: 'tkn1', name: 'Lead' },
messages: [{ msg: 'hello' }],
}); Defensive patterns
Strategy: validation
Validate before calling
// Pre-register the visitor so livechat/messages never hits the fallback path
async function ensureRegisteredVisitor(visitor: { token: string; name?: string; email?: string[] }): Promise<void> {
const res = await fetch('/api/v1/livechat/visitor', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ visitor }),
});
const body = await res.json();
if (!body.success) throw new Error(`visitor registration failed: ${body.error}`);
} Type guard
interface MinimalVisitor { token: string; name?: string; email?: { address: string }[]; department?: string }
function isValidVisitorPayload(v: unknown): v is MinimalVisitor {
const o = v as MinimalVisitor;
return typeof o?.token === 'string' && o.token.length > 0 &&
(o.email === undefined || Array.isArray(o.email)) &&
(o.department === undefined || typeof o.department === 'string');
} Try / catch
if (isLivechatErrorResponse(body) && body.error === 'error-livechat-visitor-registration') {
// registration payload rejected: log visitor payload (minus PII) and surface a configuration error, do not retry blindly
reportInvalidVisitorPayload(visitorToken);
} Prevention
- Register visitors explicitly first (livechat/visitor) and treat livechat/messages' auto-register as a convenience, not the primary path.
- Send only known-good fields: token, name, valid emails, and enabled department ids from livechat/departments.
- Remember this route requires user authentication (X-Auth-Token/X-User-Id), unlike the visitor-token routes.
When it happens
Trigger: POST /api/v1/livechat/messages with body { visitor: { token: 'new-or-unknown', ... }, messages: [...] } where the visitor object fails registration — missing name/username generation inputs, invalid visitorEmails entries, nonexistent or disabled department, or duplicate token with conflicting data.
Common situations: Integrations fabricating visitor objects by hand and omitting required fields; sending a department id that was archived; email string failing validation; payload shaped for the old registerGuest API after an upgrade tightened validation.
Related errors
- agent-not-found
- error-forwarding-chat
- error-invalid-department-unit
- error-invalid-room
- error-invalid-user
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/923493e7fb4994e5.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/omnichannel/message.ts:276
if (visitor) {
const extraQuery = await callbacks.run('livechat.applyRoomRestrictions', {}, { userId: this.userId });
const room = await LivechatRooms.findOneOpenByVisitorToken(visitorToken, { projection: { _id: 1 } }, extraQuery);
rid = room?._id ?? Random.id();
} else {
rid = Random.id();
const guest: typeof this.bodyParams.visitor & { connectionData?: unknown } = this.bodyParams.visitor;
if (settings.get('Livechat_Allow_collect_and_store_HTTP_header_informations')) {
guest.connectionData = normalizeHttpHeaderData(this.request.headers);
}
visitor = await registerGuest(guest, {
shouldConsiderIdleAgent: settings.get<boolean>('Livechat_enabled_when_agent_idle'),
shouldConsiderOfflineAgent: settings.get<boolean>('Livechat_accept_chats_with_no_agents'),
});
if (!visitor) {
throw new Error('error-livechat-visitor-registration');
}
}
const guest = visitor;
if (!guest) {
throw new Error('error-invalid-token');
}
const sentMessages = await Promise.all(
this.bodyParams.messages.map(async (message: { msg: string }): Promise<{ username: string; msg: string; ts: number }> => {
const messageToSend = {
guest,
message: {
_id: Random.id(),
rid,
token: visitorToken,
msg: message.msg,
},View on GitHub (pinned to b2c16d5842)