RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-token
error-invalid-token
Error message
Token cannot be empty
What it means
Thrown as Meteor.Error('error-invalid-token', 'Token cannot be empty') in POST livechat/visitor when bodyParams.visitor.token is missing, empty, or whitespace-only after trim. The route is unauthenticated (visitor-facing), so the token is the only identity anchor and must be non-empty.
Source
Thrown at apps/meteor/server/api/v1/omnichannel/visitor.ts:47
name: Match.Maybe(String),
email: Match.Maybe(String),
department: Match.Maybe(String),
phone: Match.Maybe(String),
username: Match.Maybe(String),
customFields: Match.Maybe([
Match.ObjectIncluding({
key: String,
value: String,
overwrite: Boolean,
}),
]),
}),
});
const { customFields, id, token, name, email, department, phone, username, connectionData } = this.bodyParams.visitor;
if (!token?.trim()) {
throw new Meteor.Error('error-invalid-token', 'Token cannot be empty', { method: 'livechat/visitor' });
}
const guest = {
token,
...(id && { id }),
...(name && { name }),
...(email && { email }),
...(department && { department }),
...(username && { username }),
...(connectionData && { connectionData }),
...(phone && typeof phone === 'string' && { phone: { number: phone as string } }),
connectionData: normalizeHttpHeaderData(this.request.headers),
};
const visitor = await registerGuest(guest, {
shouldConsiderIdleAgent: settings.get<boolean>('Livechat_enabled_when_agent_idle'),
shouldConsiderOfflineAgent: settings.get<boolean>('Livechat_accept_chats_with_no_agents'),
});View on GitHub (pinned to f9d3ec372b)
Solutions
- Generate a visitor token (UUID/v4 is typical) before calling the endpoint.
- Trim and assert non-empty client-side: if (!visitor.token?.trim()) return;
- Ensure the widget's token bootstrap runs before any registerVisitor network call.
Example fix
// before
await POST('/api/v1/livechat/visitor', { body: { visitor: { name, email } } });
// after
const token = visitor.token || crypto.randomUUID();
await POST('/api/v1/livechat/visitor', { body: { visitor: { token, name, email } } }); Defensive patterns
Strategy: validation
Validate before calling
const token = (body.visitor?.token ?? '').trim();
if (!token) throw new Error('visitor.token required');
await fetch('/api/v1/v1/livechat/visitor', { method:'POST', body: JSON.stringify({ visitor: { ...body.visitor, token } }) }); Type guard
function hasNonEmptyToken(v: { token?: string } | undefined): v is { token: string } {
return !!v?.token?.trim();
} Try / catch
null
Prevention
- Generate a visitor token (crypto.randomUUID()) at widget boot, before any register call.
- Trim and assert non-empty before POSTing.
- Treat the token as required state in the widget store.
When it happens
Trigger: POST /api/v1/v1/livechat/visitor with visitor omitted, with visitor.token = '' or ' ', or with token = null. The preceding check() validates the body shape but token is not constrained to a non-empty String there.
Common situations: Livechat widget initializing before generating a visitor token; SDK call that forgets to set token; token cleared by an upstream sanitizer.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/b0c1a6c810845978.
Report an issue: GitHub.