louislam/dockge · error · Error
Endpoint must be a string:
Error message
Endpoint must be a string:
What it means
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.
Source
Thrown at backend/socket-handlers/agent-proxy-socket-handler.ts:18
import { SocketHandler } from "../socket-handler.js";
import { DockgeServer } from "../dockge-server";
import { log } from "../log";
import { checkLogin, DockgeSocket } from "../util-server";
import { AgentSocket } from "../../common/agent-socket";
import { ALL_ENDPOINTS } from "../../common/util-common";
export class AgentProxySocketHandler extends SocketHandler {
create2(socket : DockgeSocket, server : DockgeServer, agentSocket : AgentSocket) {
// Agent - proxying requests if needed
socket.on("agent", async (endpoint : unknown, eventName : unknown, ...args : unknown[]) => {
try {
checkLogin(socket);
// Check Type
if (typeof(endpoint) !== "string") {
throw new Error("Endpoint must be a string: " + endpoint);
}
if (typeof(eventName) !== "string") {
throw new Error("Event name must be a string");
}
if (endpoint === ALL_ENDPOINTS) { // Send to all endpoints
log.debug("agent", "Sending to all endpoints: " + eventName);
socket.instanceManager.emitToAllEndpoints(eventName, ...args);
} else if (!endpoint || endpoint === socket.endpoint) { // Direct connection or matching endpoint
log.debug("agent", "Matched endpoint: " + eventName);
agentSocket.call(eventName, ...args);
} else {
log.debug("agent", "Proxying request to " + endpoint + " for " + eventName);
await socket.instanceManager.emitToEndpoint(endpoint, eventName, ...args);
}
} catch (e) {View on GitHub (pinned to f809ae192b)
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
Example fix
// before
socket.emit("agent", endpoint ?? null, "test", data);
// after
socket.emit("agent", endpoint ?? socket.endpoint, "test", data); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof endpoint !== "string" || !endpoint) { throw new TypeError("agent() requires a string endpoint"); }
socket.emit("agent", endpoint, eventName, ...args); Type guard
const isEndpoint = (v: unknown): v is string => typeof v === "string" && v.length > 0;
Try / catch
// server only logs this error; client should validate before emitting
if (!isEndpoint(ep)) { console.error("agent event skipped: endpoint must be a string, got", typeof ep); return; }
socket.emit("agent", ep, ev, ...args); Prevention
- 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[])
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Event name must be a string
- Stack name and service name must be strings
- Invalid stackName or serviceName
- isAdd must be a boolean
- Command must be a string.
AI-assisted analysis of louislam/dockge@f809ae192b (2026-08-31).
Data as JSON: /api/errors/c0352804929e8620.
Report an issue: GitHub.