{"record":{"id":"9d59a29751d6d998","repo":"RocketChat/Rocket.Chat","slug":"invalid-params-9d59a2","errorCode":"invalid-params","errorMessage":"tshow provided but missing tmid","messagePattern":"tshow provided but missing tmid","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/messages/sendMessage.ts","lineNumber":38,"sourceCode":"import { metrics } from '../../lib/metrics';\nimport { settings } from '../../settings';\n/**\n *\n * @param uid\n * @param message\n * @param extraInfo\n *   - ts: The timestamp of the message. the message object already has a ts, but this value is validated and only a window of 10 seconds is allowed to be used. this value overrides the message.ts value without validation.\n *\n *\n * @returns\n */\nexport async function executeSendMessage(\n\tuid: IUser['_id'] | IUser,\n\tmessage: AtLeast<IMessage, 'rid'>,\n\textraInfo?: { ts?: Date; previewUrls?: string[] },\n) {\n\tif (message.tshow && !message.tmid) {\n\t\tthrow new Meteor.Error('invalid-params', 'tshow provided but missing tmid', {\n\t\t\tmethod: 'sendMessage',\n\t\t});\n\t}\n\n\tif (message.tmid && !settings.get('Threads_enabled')) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'not-allowed', {\n\t\t\tmethod: 'sendMessage',\n\t\t});\n\t}\n\n\tconst isTimestampFromClient = Boolean(!extraInfo?.ts && message.ts);\n\tconst now = new Date();\n\tmessage.ts = extraInfo?.ts ?? message.ts ?? now;\n\tif (isTimestampFromClient) {\n\t\tconst tsDiff = Math.abs(moment(message.ts).diff(Date.now()));\n\t\tif (tsDiff > 60000) {\n\t\t\tthrow new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', {\n\t\t\t\tmethod: 'sendMessage',","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/messages/sendMessage.ts#L20-L56","documentation":"executeSendMessage validates thread payload shape first: if message.tshow is set but message.tmid is missing it throws invalid-params ('tshow provided but missing tmid'). tshow means 'also show this thread reply in the main channel' and is meaningless without a parent thread id, so the pair is enforced up front.","triggerScenarios":"Sending { rid, msg, tshow: true } with no tmid; client code that sets tshow first and conditionally assigns tmid later; reusing a thread-reply payload template for a normal channel message without clearing tshow.","commonSituations":"Copy-pasted message-building code where the tmid branch was removed but tshow stayed; UI toggle for 'show in channel' left on while the reply context was lost; refactor that renamed tmid but kept tshow.","solutions":["Only set tshow on actual thread replies where tmid is present","Assign tmid before tshow when building the payload so the invariant cannot be violated","For normal channel messages omit tshow entirely"],"exampleFix":"// before\nconst message = { rid, msg, tshow: true };\nawait Meteor.callAsync('sendMessage', message);\n\n// after\nconst message = { rid, msg, ...(tmid ? { tmid, tshow: true } : {}) };\nawait Meteor.callAsync('sendMessage', message);","handlingStrategy":"validation","validationCode":"// invariant: tshow requires tmid\nconst isValidThreadPayload = (m: { tmid?: string; tshow?: boolean }): boolean =>\n\t!m.tshow || Boolean(m.tmid);\n\nif (!isValidThreadPayload(message)) {\n\tdelete message.tshow;\n}\nawait Meteor.callAsync('sendMessage', message);","typeGuard":"const hasValidThreadShape = (\n\tm: { tmid?: string; tshow?: boolean },\n): m is { tmid: string; tshow?: boolean } =>\n\ttypeof m.tmid === 'string' && m.tmid.length > 0 && (!('tshow' in m) || !m.tshow || true) && Boolean(m.tshow) === Boolean(m.tshow && m.tmid);","tryCatchPattern":"try {\n\tawait Meteor.callAsync('sendMessage', message);\n} catch (e: any) {\n\tif (e?.error === 'invalid-params' && e?.reason?.includes('tshow')) {\n\t\t// payload bug: rebuild with tmid set or tshow removed, then resend\n\t}\n\tthrow e;\n}","preventionTips":["Build thread payloads by assigning tmid before tshow","Add a unit test asserting tshow is never sent without tmid","Strip thread-only fields when reusing payload templates for normal messages"],"tags":["meteor-method","messages","threads","validation"],"backgroundTag":"missing-required-parameter","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}