{"record":{"id":"b3249f0b0286e81f","repo":"RocketChat/Rocket.Chat","slug":"invalid-token-b3249f","errorCode":"invalid-token","errorMessage":"invalid-token","messagePattern":"invalid-token","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/omnichannel/sendMessageLivechat.ts","lineNumber":56,"sourceCode":"\tcheck(\n\t\tagent,\n\t\tMatch.Maybe({\n\t\t\tagentId: String,\n\t\t\tusername: String,\n\t\t}),\n\t);\n\n\tconst guest = await LivechatVisitors.getVisitorByToken(token, {\n\t\tprojection: {\n\t\t\tname: 1,\n\t\t\tusername: 1,\n\t\t\tdepartment: 1,\n\t\t\ttoken: 1,\n\t\t},\n\t});\n\n\tif (!guest) {\n\t\tthrow new Meteor.Error('invalid-token');\n\t}\n\n\tif (settings.get('Livechat_enable_message_character_limit') && msg.length > parseInt(settings.get('Livechat_message_character_limit'))) {\n\t\tthrow new Meteor.Error('message-length-exceeds-character-limit');\n\t}\n\n\treturn sendMessage({\n\t\tguest,\n\t\tmessage: {\n\t\t\t_id,\n\t\t\trid,\n\t\t\tmsg,\n\t\t\ttoken,\n\t\t\tfile,\n\t\t\tfiles,\n\t\t\tattachments,\n\t\t},\n\t\tagent,","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/omnichannel/sendMessageLivechat.ts#L38-L74","documentation":"The sendMessageLivechat Meteor method (deprecated since 9.0.0 in favor of /v1/livechat/message) authenticates the sender purely by visitor token: LivechatVisitors.getVisitorByToken(token) found no matching document, so the send is rejected with invalid-token. The token must belong to an existing livechat visitor on this workspace.","triggerScenarios":"Calling sendMessageLivechat with a message whose token was never registered, belongs to another workspace/environment, or whose visitor was deleted; a stale token persisted in the widget's localStorage after a data reset or server migration.","commonSituations":"Livechat widget reusing an old localStorage token after the server was reinstalled or visitors purged; dev vs prod token mixups; hand-rolled integrations that invent tokens instead of registering a visitor first.","solutions":["Register (or restore) the livechat visitor before sending and use the token returned by that registration for all sends","Clear the stale guest token in the widget (localStorage) so a new visitor and token are generated","Confirm the token comes from the same workspace/environment — tokens do not transfer across servers"],"exampleFix":"// before\nMeteor.call('sendMessageLivechat', { token: staleToken, _id, rid, msg });\n\n// after\nconst { visitor } = await registerLivechatVisitor(); // returns a valid token\nMeteor.call('sendMessageLivechat', { token: visitor.token, _id, rid, msg });","handlingStrategy":"retry","validationCode":"const info = await fetch(`/api/v1/livechat/visitor.info?token=${encodeURIComponent(token)}`);\nif (!info.ok) {\n  const reg = await registerLivechatVisitor();\n  token = reg.token; // refresh the dead token before sending\n}","typeGuard":"const isInvalidToken = (e: unknown): e is Meteor.Error =>\n  typeof e === 'object' && e !== null && (e as { error?: string }).error === 'invalid-token';","tryCatchPattern":"try {\n  await send(token);\n} catch (e) {\n  if (isInvalidToken(e)) {\n    token = (await registerLivechatVisitor()).token; // acquire a fresh, valid visitor identity\n    return send(token); // one retry with the new token\n  }\n  throw e;\n}","preventionTips":["Create or restore the visitor and persist its token before any livechat send","Treat invalid-token as session loss: regenerate the visitor token and continue instead of hard-failing","Scope stored tokens per environment — tokens never transfer between workspaces"],"tags":["rocket-chat","livechat","omnichannel","visitor-token","authentication","deprecation"],"backgroundTag":"invalid-auth-token","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}