{"record":{"id":"d4a8ac1ddb93e2a6","repo":"RocketChat/Rocket.Chat","slug":"no-agent-online-d4a8ac","errorCode":"no-agent-online","errorMessage":"no-agent-online","messagePattern":"no-agent-online","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/routing/External.ts","lineNumber":33,"sourceCode":"\t\t\tpreviewRoom: false,\n\t\t\tshowConnecting: false,\n\t\t\tshowQueue: false,\n\t\t\tshowQueueLink: false,\n\t\t\treturnQueue: false,\n\t\t\tenableTriggerAction: true,\n\t\t\tautoAssignAgent: true,\n\t\t};\n\t}\n\n\tasync getNextAgent(department?: string, ignoreAgentId?: string): Promise<SelectedAgent | null | undefined> {\n\t\tconst promises = [];\n\t\tfor (let i = 0; i < 10; i++) {\n\t\t\tpromises.push(this.getAgentFromExternalQueue(department, ignoreAgentId));\n\t\t}\n\t\ttry {\n\t\t\tconst results = (await Promise.all(promises)).filter(Boolean);\n\t\t\tif (!results.length) {\n\t\t\t\tthrow new Meteor.Error('no-agent-online', 'Sorry, no online agents');\n\t\t\t}\n\t\t\treturn results[0];\n\t\t} catch (err) {\n\t\t\tSystemLogger.error({ msg: 'Error requesting agent from external queue.', err });\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tprivate async getAgentFromExternalQueue(department?: string, ignoreAgentId?: string): Promise<SelectedAgent | null | undefined> {\n\t\ttry {\n\t\t\tconst request = await fetch(`${settings.get('Livechat_External_Queue_URL')}`, {\n\t\t\t\theaders: {\n\t\t\t\t\t'User-Agent': 'RocketChat Server',\n\t\t\t\t\t'Accept': 'application/json',\n\t\t\t\t\t'X-RocketChat-Secret-Token': settings.get('Livechat_External_Queue_Token'),\n\t\t\t\t},\n\t\t\t\tparams: {\n\t\t\t\t\t...(department && { departmentId: department }),","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/routing/External.ts#L15-L51","documentation":"Thrown by the External routing method when Rocket.Chat delegates agent selection to an external queue service. getNextAgent fires 10 parallel requests to the Livechat_External_Queue_URL; every request that fails or returns nothing is filtered out with Boolean, and if nothing remains it throws 'no-agent-online' ('Sorry, no online agents'). The catch block logs the underlying error to SystemLogger and rethrows.","triggerScenarios":"Omnichannel routing method set to 'External' (Livechat_Routing_Method) and a new inquiry needs an agent, while the external queue endpoint is unreachable, returns non-2xx/an error (getAgentFromExternalQueue swallows these and returns null), returns an empty agent payload, or the external system genuinely has no online agents.","commonSituations":"Livechat_External_Queue_URL misconfigured (wrong URL, missing protocol or path), the external queue service is down or restarting, network egress blocked from the Rocket.Chat server, response schema mismatch with the expected SelectedAgent JSON, or all agents offline in the external system.","solutions":["Verify the Livechat_External_Queue_URL setting value in Admin > Omnichannel > Routing","curl the endpoint from the Rocket.Chat server and confirm it returns a valid agent (SelectedAgent-shaped) JSON body","Check SystemLogger for 'Error requesting agent from external queue.' entries containing the real err (DNS, timeout, 401, etc.)","Confirm the external queue actually has online agents for that department","If the external service is permanently unavailable, switch Livechat_Routing_Method back to Auto_Selection or Load_Balancing as a fallback"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// health-check the external queue before relying on it\nimport { settings } from '../settings';\n\nasync function externalQueueHealthy(): Promise<boolean> {\n  const url = settings.get<string>('Livechat_External_Queue_URL');\n  if (!url) return false;\n  try {\n    const res = await fetch(url, { signal: AbortSignal.timeout(3000) });\n    return res.ok;\n  } catch {\n    return false;\n  }\n}","typeGuard":"type SelectedAgent = { agentId: string; username?: string };\n\nfunction isSelectedAgent(v: unknown): v is SelectedAgent {\n  return typeof v === 'object' && v !== null && typeof (v as SelectedAgent).agentId === 'string';\n}","tryCatchPattern":"try {\n  agent = await routingManager.getNextAgent(departmentId);\n} catch (err) {\n  if (err instanceof Meteor.Error && err.error === 'no-agent-online') {\n    // degrade gracefully: fall back to internal routing or queue for retry\n    agent = await internalAutoSelection(departmentId);\n  } else {\n    throw err;\n  }\n}","preventionTips":["Monitor the external queue endpoint with a synthetic probe and page before it goes down","Validate Livechat_External_Queue_URL from the server network (curl/fetch) after every settings change","Log and alert on SystemLogger 'Error requesting agent from external queue' — it carries the real cause","Document the expected SelectedAgent JSON contract with the external system owners"],"tags":["omnichannel","routing","external-queue","network","fetch"],"backgroundTag":"external-service-unavailable","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"}