{"record":{"id":"15b3f024ec40a252","repo":"can1357/oh-my-pi","slug":"daemon-broker-authentication-failed","errorCode":null,"errorMessage":"Daemon broker authentication failed","messagePattern":"Daemon broker authentication failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/launch/broker.ts","lineNumber":477,"sourceCode":"\t\t});\n\t\tsocket.on(\"close\", () => {\n\t\t\tthis.#sockets.delete(socket);\n\t\t\tif (!authenticated) return;\n\t\t\tthis.#clients.delete(socket);\n\t\t\tthis.#scheduleIdleShutdown();\n\t\t\tfor (const [owner, registration] of this.#ownerSockets) {\n\t\t\t\tif (registration.socket === socket) this.#ownerSockets.delete(owner);\n\t\t\t}\n\t\t});\n\t}\n\n\tasync #handleLine(socket: net.Socket, line: string, onAuthenticated: () => void): Promise<void> {\n\t\tlet id = \"unknown\";\n\t\ttry {\n\t\t\tconst decoded: unknown = JSON.parse(line);\n\t\t\tconst request = parseDaemonWireRequest(decoded);\n\t\t\tid = request.id;\n\t\t\tif (request.token !== this.#token) throw new Error(\"Daemon broker authentication failed\");\n\t\t\tonAuthenticated();\n\t\t\tfor (const owner of request.completionUnsubscribes ?? []) {\n\t\t\t\tconst subscriptionId = this.#completionSubscriptions.get(owner);\n\t\t\t\tif (\n\t\t\t\t\t!this.#completionSubscriptions.has(owner) ||\n\t\t\t\t\t(subscriptionId !== undefined && subscriptionId !== request.completionSubscriptionId)\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.#ownerSockets.delete(owner);\n\t\t\t\tthis.#completionSubscriptions.delete(owner);\n\t\t\t\tawait this.#setRecordCompletionCapability(owner, false);\n\t\t\t\tthis.#pendingCompletions.delete(owner);\n\t\t\t}\n\t\t\tfor (const completionId of request.completionAcks ?? []) {\n\t\t\t\tfor (const [owner, pending] of this.#pendingCompletions) {\n\t\t\t\t\tconst registration = this.#ownerSockets.get(owner);\n\t\t\t\t\tif (","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/launch/broker.ts#L459-L495","documentation":"DaemonBroker's socket line handler parses each inbound line as a daemon wire request and compares request.token against the broker's shared secret (#token). Any mismatch throws 'Daemon broker authentication failed' before the request is dispatched or the socket is marked authenticated, protecting the local daemon-control RPC from unauthorized processes on the machine.","triggerScenarios":"A client connects to the broker's socket and sends a wire request whose token field differs from the broker's configured token — wrong or stale token file, token regenerated after broker restart, or an unauthenticated/malicious local process probing the socket.","commonSituations":"Client and broker reading the token from different locations after a config change or reinstall; multiple broker versions running concurrently with independently generated tokens; a client cached an old token from a previous daemon lifetime; local security tooling or another user's process port-scanning the socket.","solutions":["Ensure the client loads the same token the broker was started with (same token file / env source) and restart the client","Restart the broker so it and its clients are recreated from one token source together","Check for stale broker instances (kill old daemons/brokers) so you are not authenticating against a defunct token","If you own the wire client, log the token source (not the token) on both sides to confirm they resolve to the same file"],"exampleFix":"// before\nconst token = readToken('~/.omp/daemon.token'); // stale file from previous install\nsend(socket, { id, op: 'start', token }); // Daemon broker authentication failed\n// after\nconst token = await brokerClient.currentToken(); // read live token from broker's authoritative location\nsend(socket, { id, op: 'start', token });","handlingStrategy":"try-catch","validationCode":"const expectedToken = await readBrokerToken(); // same authoritative source the broker uses\nif (!request.token || request.token !== expectedToken) {\n  throw new Error('Refusing to send: client token does not match broker token');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await daemonRpc(request);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Daemon broker authentication failed') {\n    await refreshBrokerToken(); // re-read token file / restart broker\n    return daemonRpc({ ...request, token: currentToken() });\n  }\n  throw err;\n}","preventionTips":["Read the token from the broker's canonical location at connect time, never cache it across broker restarts","Version-bump the token file path when the install layout changes so stale tokens are not silently reused","Kill superseded broker instances before starting a new one to avoid authenticating against the wrong process","Never log or embed tokens in configs, scripts, or error reports"],"tags":["authentication","security","ipc","daemon"],"backgroundTag":"auth-token-mismatch","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}