{"record":{"id":"c8a7c35c53997003","repo":"RocketChat/Rocket.Chat","slug":"invalid-service-url","errorCode":null,"errorMessage":"Invalid service URL","messagePattern":"Invalid service URL","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/ee/server/api/v1/omnichannel/triggers.ts","lineNumber":93,"sourceCode":"\t\tasync post() {\n\t\t\tconst { _id: triggerId } = this.urlParams;\n\t\t\tconst { token: visitorToken, extraData } = this.bodyParams;\n\n\t\t\tconst trigger = await LivechatTrigger.findOneById(triggerId);\n\n\t\t\tif (!trigger) {\n\t\t\t\tthrow new Error('Invalid trigger');\n\t\t\t}\n\n\t\t\tif (!trigger?.actions.length || !isExternalServiceTrigger(trigger)) {\n\t\t\t\tthrow new Error('Trigger is not configured to use an external service');\n\t\t\t}\n\n\t\t\tconst { params: { serviceTimeout = 5000, serviceUrl, serviceFallbackMessage = 'trigger-default-fallback-message' } = {} } =\n\t\t\t\ttrigger.actions[0];\n\n\t\t\tif (!serviceUrl) {\n\t\t\t\tthrow new Error('Invalid service URL');\n\t\t\t}\n\n\t\t\tconst token = settings.get<string>('Livechat_secret_token');\n\n\t\t\tif (!token) {\n\t\t\t\tthrow new Error('Livechat secret token is not configured');\n\t\t\t}\n\n\t\t\tconst body = {\n\t\t\t\tmetadata: extraData,\n\t\t\t\tvisitorToken,\n\t\t\t};\n\n\t\t\tconst headers = {\n\t\t\t\t'Accept': 'application/json',\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t'X-RocketChat-Livechat-Token': token,\n\t\t\t};","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/ee/server/api/v1/omnichannel/triggers.ts#L75-L111","documentation":"Thrown by POST livechat/triggers/:_id/external-service/call after the trigger passes the isExternalServiceTrigger guard, when trigger.actions[0].params has no serviceUrl (it is undefined or empty). The destructuring reads params.serviceUrl, so a saved action whose params object is missing serviceUrl, or where params itself is undefined, reaches this throw.","triggerScenarios":"The trigger's action was created with name 'use-external-service' but its params object omitted serviceUrl (or left it as an empty string). The external-service/call endpoint then cannot form an outbound POST because no target URL exists.","commonSituations":"A trigger was partially configured through the UI (action type chosen, but the webhook URL field left blank), or created via API with a params object that lacks the serviceUrl key. Migration scripts that rebuilt trigger documents can also drop serviceUrl.","solutions":["Edit the trigger and fill in the service URL field under the 'Use an external service' action.","Via the REST API, PATCH/recreate the trigger so actions[0].params.serviceUrl is a non-empty https URL.","Validate the trigger document in mongo (db.livechat_trigger.findOne) to confirm params.serviceUrl is present before relying on the endpoint.","If the URL was intentionally empty, switch the action to a different type instead of leaving it half-configured."],"exampleFix":"// before - serviceUrl missing from params\n{ \"name\": \"use-external-service\", \"params\": { \"sender\": \"queue\", \"name\": \"bot\" } }\n\n// after\n{ \"name\": \"use-external-service\", \"params\": { \"sender\": \"queue\", \"name\": \"bot\", \"serviceUrl\": \"https://bot.example.com/inbox\", \"serviceTimeout\": 5000, \"serviceFallbackMessage\": \"fallback\" } }","handlingStrategy":"validation","validationCode":"function hasServiceUrl(trigger): boolean {\n  return Boolean(trigger?.actions?.[0]?.params?.serviceUrl);\n}\n\nif (!hasServiceUrl(trigger)) {\n  return showAdminConfigError('serviceUrl is missing on the external-service trigger');\n}","typeGuard":"const isExternalServiceActionWithUrl = (\n  action: unknown\n): action is { name: 'use-external-service'; params: { serviceUrl: string } } =>\n  typeof action === 'object' &&\n  (action as any)?.name === 'use-external-service' &&\n  typeof (action as any)?.params?.serviceUrl === 'string' &&\n  (action as any).params.serviceUrl.length > 0;","tryCatchPattern":"try {\n  await triggerExternalServiceCall(triggerId, visitorToken);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Invalid service URL') {\n    notifyAdminToConfigureServiceUrl(triggerId);\n  }\n}","preventionTips":["When creating a trigger via API, require params.serviceUrl in the request schema (ajv).","Run a migration/check that flags any external-service trigger with a missing serviceUrl.","Treat serviceUrl as a required field in your admin UI, not optional."],"tags":["omnichannel","livechat-trigger","configuration","validation"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}