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

  1. 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.
  2. If passing department, use an enabled department id from GET /api/v1/livechat/departments and provide valid email arrays.
  3. Check server logs — registerGuest failures around registration (department resolution, validation) are logged and pinpoint the offending field.
  4. 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

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


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)