{"record":{"id":"79364633f8015bd2","repo":"RocketChat/Rocket.Chat","slug":"invalid-status-code","errorCode":null,"errorMessage":"Invalid status code","messagePattern":"Invalid status code","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"warning","filePath":"apps/meteor/server/api/v1/omnichannel/webhooks.ts","lineNumber":88,"sourceCode":"\t\t\t} as ExtendedFetchOptions;\n\n\t\t\tconst webhookUrl = settings.get<string>('Livechat_webhookUrl');\n\n\t\t\tif (!webhookUrl) {\n\t\t\t\treturn API.v1.failure('Webhook_URL_not_set');\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tlogger.debug({ msg: 'Testing webhook', webhookUrl });\n\t\t\t\tconst request = await fetch(webhookUrl, options);\n\t\t\t\tconst response = await request.text();\n\n\t\t\t\tlogger.debug({ msg: 'Webhook response', response });\n\t\t\t\tif (request.status === 200) {\n\t\t\t\t\treturn API.v1.success();\n\t\t\t\t}\n\n\t\t\t\tthrow new Error('Invalid status code');\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error({ msg: 'Error testing webhook', err: error });\n\t\t\t\tthrow new Error('error-invalid-webhook-response');\n\t\t\t}\n\t\t},\n\t},\n);\n","sourceCodeStart":70,"sourceCodeEnd":96,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/v1/omnichannel/webhooks.ts#L70-L96","documentation":"Internal marker thrown by POST /api/v1/livechat/webhook.test when the configured Livechat_webhookUrl answered the sample payload with any final HTTP status other than 200. It never reaches the client: the surrounding catch logs it under the WebhookTest logger and re-throws error-invalid-webhook-response, so 'Invalid status code' only ever appears in server logs/debug output as the reason behind the outer failure.","triggerScenarios":"POST /api/v1/livechat/webhook.test (needs view-livechat-webhooks permission and Livechat_webhookUrl set) while the receiver endpoint replies 201/202/204, a 4xx auth rejection, or a 5xx — fetch follows redirects, so the final status after any 3xx hop is what counts.","commonSituations":"Receiver returns 201 Created or 204 No Content on success — Rocket.Chat insists on exactly 200; receiver rejects the X-RocketChat-Livechat-Token header (secret mismatch) with 401/403; framework default error pages (502 from a proxy) when the handler crashes on the sample payload's shape.","solutions":["Replay the test yourself: POST the sample LivechatSession payload with header X-RocketChat-Livechat-Token to your endpoint and confirm it returns exactly HTTP 200","If your service legitimately answers 201/204 on success, add a wrapper route that answers 200 for this integration","Check the receiver's own logs for crashes on the sample payload (it contains visitor/agent/messages objects with ISO dates)"],"exampleFix":"// before (Express handler answering 201)\nres.status(201).json({ ok: true });\n\n// after (Rocket.Chat webhook.test requires 200)\nres.status(200).json({ ok: true });","handlingStrategy":"validation","validationCode":"# validate your receiver answers 200 before wiring it into Rocket.Chat\ncurl -i -X POST https://receiver.example/webhook \\\n  -H \"X-RocketChat-Livechat-Token: $LIVECHAT_SECRET_TOKEN\" \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"type\":\"LivechatSession\",\"_id\":\"test\"}'\n# the first line must read: HTTP/1.1 200","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make the webhook receiver answer exactly 200 on the integration path (not 201/204)","Verify the Livechat_secret_token header check passes before any body processing","Log the status your receiver produced so Rocket.Chat's log and yours can be correlated"],"tags":["omnichannel","webhook","integration","http-status","livechat"],"backgroundTag":"webhook-bad-status-code","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}