{"record":{"id":"c0352804929e8620","repo":"louislam/dockge","slug":"endpoint-must-be-a-string","errorCode":null,"errorMessage":"Endpoint must be a string: ","messagePattern":"Endpoint must be a string: ","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"backend/socket-handlers/agent-proxy-socket-handler.ts","lineNumber":18,"sourceCode":"import { SocketHandler } from \"../socket-handler.js\";\nimport { DockgeServer } from \"../dockge-server\";\nimport { log } from \"../log\";\nimport { checkLogin, DockgeSocket } from \"../util-server\";\nimport { AgentSocket } from \"../../common/agent-socket\";\nimport { ALL_ENDPOINTS } from \"../../common/util-common\";\n\nexport class AgentProxySocketHandler extends SocketHandler {\n\n    create2(socket : DockgeSocket, server : DockgeServer, agentSocket : AgentSocket) {\n        // Agent - proxying requests if needed\n        socket.on(\"agent\", async (endpoint : unknown, eventName : unknown, ...args : unknown[]) => {\n            try {\n                checkLogin(socket);\n\n                // Check Type\n                if (typeof(endpoint) !== \"string\") {\n                    throw new Error(\"Endpoint must be a string: \" + endpoint);\n                }\n                if (typeof(eventName) !== \"string\") {\n                    throw new Error(\"Event name must be a string\");\n                }\n\n                if (endpoint === ALL_ENDPOINTS) {      // Send to all endpoints\n                    log.debug(\"agent\", \"Sending to all endpoints: \" + eventName);\n                    socket.instanceManager.emitToAllEndpoints(eventName, ...args);\n\n                } else if (!endpoint || endpoint === socket.endpoint) {      // Direct connection or matching endpoint\n                    log.debug(\"agent\", \"Matched endpoint: \" + eventName);\n                    agentSocket.call(eventName, ...args);\n\n                } else {\n                    log.debug(\"agent\", \"Proxying request to \" + endpoint + \" for \" + eventName);\n                    await socket.instanceManager.emitToEndpoint(endpoint, eventName, ...args);\n                }\n            } catch (e) {","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/louislam/dockge/blob/f809ae192b571944ad773e9866d3e67064ae8043/backend/socket-handlers/agent-proxy-socket-handler.ts#L1-L36","documentation":"The agent proxy socket handler wraps the `agent` event and type-checks its arguments before forwarding them to agent endpoints. If `endpoint` is not a string it throws 'Endpoint must be a string: <value>'. Unlike most handlers here, this error is only logged (log.warn) — the promise catches it silently for the client.","triggerScenarios":"Emitting socket event `agent` with a non-string first argument, e.g. socket.emit('agent', null, 'test', payload), or passing an object endpoint, or omitting it (undefined).","commonSituations":"Client sending endpoint as undefined because it never bound to an endpoint; JSON payloads where endpoint was nested; custom scripts calling the raw socket API without the frontend wrapper.","solutions":["Always pass a string endpoint: socket.emit('agent', 'myendpoint', 'eventName', ...args)","Use the ALL_ENDPOINTS sentinel string to broadcast instead of null/undefined","On the client, default the endpoint from socket.endpoint when connected directly"],"exampleFix":"// before\nsocket.emit(\"agent\", endpoint ?? null, \"test\", data);\n// after\nsocket.emit(\"agent\", endpoint ?? socket.endpoint, \"test\", data);","handlingStrategy":"type-guard","validationCode":"if (typeof endpoint !== \"string\" || !endpoint) { throw new TypeError(\"agent() requires a string endpoint\"); }\nsocket.emit(\"agent\", endpoint, eventName, ...args);","typeGuard":"const isEndpoint = (v: unknown): v is string => typeof v === \"string\" && v.length > 0;","tryCatchPattern":"// server only logs this error; client should validate before emitting\nif (!isEndpoint(ep)) { console.error(\"agent event skipped: endpoint must be a string, got\", typeof ep); return; }\nsocket.emit(\"agent\", ep, ev, ...args);","preventionTips":["Default endpoint to socket.endpoint instead of null/undefined","Use the ALL_ENDPOINTS constant for broadcasts","Type the agent emitter helper with (endpoint: string, eventName: string, ...args: unknown[])"],"tags":["validation","socket-io","agent","typescript"],"backgroundTag":"invalid-argument-type","analyzedSha":"f809ae192b571944ad773e9866d3e67064ae8043","analyzedAt":"2026-08-31T19:13:50.919Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}