{"record":{"id":"d09933ae5f938c58","repo":"RocketChat/Rocket.Chat","slug":"invalid-token-d09933","errorCode":null,"errorMessage":"invalid-token","messagePattern":"invalid-token","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/customField.ts","lineNumber":30,"sourceCode":"\tvalidateUnauthorizedErrorResponse,\n} from '@rocket.chat/rest-typings';\n\nimport { API } from '../..';\nimport { setCustomFields, setMultipleCustomFields } from '../../../lib/omnichannel/custom-fields';\nimport type { ExtractRoutesFromAPI } from '../../ApiClass';\nimport { findLivechatCustomFields, findCustomFieldById } from './lib/customFields';\nimport { findGuest } from './lib/livechat';\nimport { getPaginationItems } from '../../lib/getPaginationItems';\n\nAPI.v1.addRoute(\n\t'livechat/custom.field',\n\t{ validateParams: isPOSTLivechatCustomFieldParams },\n\t{\n\t\tasync post() {\n\t\t\tconst { token, key, value, overwrite } = this.bodyParams;\n\t\t\tconst guest = await findGuest(token);\n\t\t\tif (!guest) {\n\t\t\t\tthrow new Error('invalid-token');\n\t\t\t}\n\n\t\t\tawait setCustomFields({ token, key, value, overwrite });\n\n\t\t\treturn API.v1.success({ field: { key, value, overwrite } });\n\t\t},\n\t},\n);\n\nAPI.v1.addRoute(\n\t'livechat/custom.fields',\n\t{ validateParams: isPOSTLivechatCustomFieldsParams },\n\t{\n\t\tasync post() {\n\t\t\tconst { token } = this.bodyParams;\n\t\t\tconst visitor = await findGuest(token);\n\t\t\tif (!visitor) {\n\t\t\t\tthrow new Error('invalid-token');","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/v1/omnichannel/customField.ts#L12-L48","documentation":"POST /api/v1/livechat/custom.field sets one custom field for a visitor identified by the body token. findGuest(token) maps to LivechatVisitors.getVisitorByToken(token); when no visitor document carries that token the endpoint throws 'invalid-token' before any field is written.","triggerScenarios":"POSTing livechat/custom.field with a token that was never registered, was mistyped, belongs to another environment (staging vs prod), or whose visitor document was deleted.","commonSituations":"Widget/integration persists an old token after the visitors collection was reset or the visitor re-registered; copy-paste between servers; token lost from localStorage so an empty/stale value is sent.","solutions":["Use the exact token returned when the visitor was created (POST /api/v1/livechat/visitor returns visitor.token) in the same environment.","Verify the token first with the visitor-info-by-token endpoint; if it no longer resolves, re-register the visitor and store the new token.","Never reuse tokens across deployments; make the token part of per-environment configuration."],"exampleFix":"// before\nawait post('/api/v1/livechat/custom.field', { token: staleToken, key: 'plan', value: 'pro' }); // invalid-token\n\n// after\nasync function ensureGuest() {\n  const info = await get(`/api/v1/livechat/visitor.info/${token}`);\n  if (!info?.visitor) {\n    const { visitor } = await post('/api/v1/livechat/visitor', { visitor: { name: 'guest' } });\n    token = visitor.token; // persist this\n  }\n  return token;\n}\nawait post('/api/v1/livechat/custom.field', { token: await ensureGuest(), key: 'plan', value: 'pro' });","handlingStrategy":"try-catch","validationCode":"// Verify the visitor token before writing a custom field\nconst info = await get(`/api/v1/livechat/visitor.info/${token}`);\nif (!info?.visitor) throw new Error('visitor token no longer valid; re-register guest');\nawait post('/api/v1/livechat/custom.field', { token, key, value, overwrite });","typeGuard":null,"tryCatchPattern":"try {\n  await post('/api/v1/livechat/custom.field', { token, key, value });\n} catch (e) {\n  if (e.message !== 'invalid-token') throw e;\n  const { visitor } = await post('/api/v1/livechat/visitor', { visitor: { name: 'guest' } });\n  token = visitor.token; // persist new token\n  await post('/api/v1/livechat/custom.field', { token, key, value });\n}","preventionTips":["Store the token returned by visitor registration and never reuse tokens across environments.","Pair the token write with the same lifecycle as the visitor record.","Verify tokens after workspace resets/migrations."],"tags":["omnichannel","livechat","custom-fields","visitor-token","rest-api"],"backgroundTag":"invalid-auth-token","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}