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

  1. Verify the token is correct and was issued by this server instance.
  2. Register a new visitor via POST /api/v1/livechat/visitor to obtain a valid token.
  3. 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

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.