RocketChat/Rocket.Chat · error · Error
invalid-token
Error message
invalid-token
What it means
Thrown by POST /api/v1/livechat/custom.field when findGuest(token) returns null. The endpoint accepts a visitor token in the body and looks up the corresponding livechat guest via LivechatVisitors.getVisitorByToken. If no visitor matches, the token is invalid.
Source
Thrown at apps/meteor/server/api/v1/omnichannel/customField.ts:30
validateUnauthorizedErrorResponse,
} from '@rocket.chat/rest-typings';
import { API } from '../..';
import { setCustomFields, setMultipleCustomFields } from '../../../lib/omnichannel/custom-fields';
import type { ExtractRoutesFromAPI } from '../../ApiClass';
import { findLivechatCustomFields, findCustomFieldById } from './lib/customFields';
import { findGuest } from './lib/livechat';
import { getPaginationItems } from '../../lib/getPaginationItems';
API.v1.addRoute(
'livechat/custom.field',
{ validateParams: isPOSTLivechatCustomFieldParams },
{
async post() {
const { token, key, value, overwrite } = this.bodyParams;
const guest = await findGuest(token);
if (!guest) {
throw new Error('invalid-token');
}
await setCustomFields({ token, key, value, overwrite });
return API.v1.success({ field: { key, value, overwrite } });
},
},
);
API.v1.addRoute(
'livechat/custom.fields',
{ validateParams: isPOSTLivechatCustomFieldsParams },
{
async post() {
const { token } = this.bodyParams;
const visitor = await findGuest(token);
if (!visitor) {
throw new Error('invalid-token');View on GitHub (pinned to f9d3ec372b)
Solutions
- Verify the token is correct and was issued by this server instance.
- Register a new visitor via POST /api/v1/livechat/visitor to obtain a valid token.
- Check that the visitor hasn't been purged by retention policies.
Example fix
// before: posting with an unknown token
POST /api/v1/livechat/custom.field
{ "token": "bad-token", "key": "company", "value": "Acme" }
// after: register visitor first, then set custom field
POST /api/v1/livechat/visitor { "visitor": { "token": "valid-token-123" } }
POST /api/v1/livechat/custom.field { "token": "valid-token-123", "key": "company", "value": "Acme" } Defensive patterns
Strategy: validation
Validate before calling
// Verify the visitor token is valid before setting a custom field
async function ensureValidVisitor(baseUrl, token) {
const res = await fetch(`${baseUrl}/api/v1/livechat/visitor/${token}`);
if (!res.ok) {
// Register a new visitor
const regRes = await fetch(`${baseUrl}/api/v1/livechat/visitor`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ visitor: { token } })
});
return regRes.ok;
}
return true;
} Type guard
function isValidVisitorToken(token: unknown): token is string {
return typeof token === 'string' && token.trim().length > 0;
} Try / catch
try {
await setCustomField({ token, key, value, overwrite });
} catch (e) {
if (e.message === 'invalid-token') {
// Re-register the visitor and retry
await registerVisitor(token);
return setCustomField({ token, key, value, overwrite });
}
throw e;
} Prevention
- Register the visitor via POST /api/v1/livechat/visitor before using the token in custom field endpoints.
- Store visitor tokens securely after registration.
- Handle invalid-token errors by re-registering the visitor.
When it happens
Trigger: Posting to custom.field with a visitor token that does not exist in the LivechatVisitors collection — the token was never issued by this server, was for a different instance, or the visitor record was purged.
Common situations: Stale token from a prior server instance; visitor record deleted by retention cleanup; token typo; token from a different environment (test vs production).
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/d09933ae5f938c58.
Report an issue: GitHub.