{"record":{"id":"66ad7f2a6aba411d","repo":"can1357/oh-my-pi","slug":"line","errorCode":null,"errorMessage":"line","messagePattern":"line","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/cmux/socket-client.ts","lineNumber":162,"sourceCode":"\t\tconst socket = relayEndpoint\n\t\t\t? net.createConnection({ host: relayEndpoint.host, port: relayEndpoint.port })\n\t\t\t: net.createConnection({ path: this.#socketPath });\n\t\tthis.#socket = socket;\n\t\tthis.#buffer = \"\";\n\t\tsocket.setEncoding(\"utf8\");\n\t\tsocket.on(\"data\", chunk => this.#onData(String(chunk)));\n\t\tsocket.on(\"error\", err => this.#handleSocketFailure(err));\n\t\tsocket.on(\"close\", () => this.#handleSocketClose());\n\n\t\ttry {\n\t\t\tawait this.#waitForConnect(socket);\n\t\t\tif (relayEndpoint && relayCredentials) {\n\t\t\t\tawait this.#authenticateRelay(relayEndpoint, relayCredentials);\n\t\t\t}\n\t\t\tif (this.#password) {\n\t\t\t\tconst line = await this.#sendLine(`auth ${this.#password}`, DEFAULT_CONNECT_TIMEOUT_MS);\n\t\t\t\tif (line.startsWith(\"ERROR:\") && !line.includes(\"Unknown command 'auth'\")) {\n\t\t\t\t\tthrow new ToolError(line);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.#connected = true;\n\t\t} catch (err) {\n\t\t\tthis.#connected = false;\n\t\t\tsocket.destroy();\n\t\t\tif (err instanceof ToolError) throw err;\n\t\t\tthrow new ToolError(\n\t\t\t\t`Failed to connect to cmux socket at ${this.#socketPath}: ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t#parseRelayEndpoint(): RelayEndpoint | null {\n\t\tconst value = this.#socketPath.trim();\n\t\tif (value.length === 0 || value.startsWith(\"/\")) {\n\t\t\treturn null;\n\t\t}","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/cmux/socket-client.ts#L144-L180","documentation":"During #openSocket, after the TCP/socket connect succeeds, the client optionally sends `auth <password>` to the cmux daemon. If the daemon replies with an `ERROR:` line — and it is not the tolerated 'Unknown command \\'auth\\'' case (older daemons without auth support) — the raw error line is thrown as a ToolError. This means the daemon explicitly rejected the authentication handshake.","triggerScenarios":"Configuring CMUX_SOCKET_PASSWORD (or the password option) with a wrong password while the daemon has auth enabled; daemon expects a password but the supplied one mismatches; a daemon that rejects the auth command semantics with an ERROR other than the unknown-command case.","commonSituations":"Rotated daemon password not synced to the client env; stale CMUX_SOCKET_PASSWORD from a previous cmux session; connecting to the wrong daemon instance that has different credentials.","solutions":["Correct the password (CMUX_SOCKET_PASSWORD env or the password option) to match the running cmux daemon","Verify which daemon instance owns the socket path and its current credentials","If the daemon genuinely has no auth, unset the password — but check the ERROR line first, since 'Unknown command auth' is tolerated automatically"],"exampleFix":"// before\nexport CMUX_SOCKET_PASSWORD=old-secret\n// after\nexport CMUX_SOCKET_PASSWORD=$(cat ~/.cmux/socket.password)","handlingStrategy":"try-catch","validationCode":"// verify the password source before connecting\nconst password = process.env.CMUX_SOCKET_PASSWORD;\nif (password && !fs.existsSync(passwordFile)) throw new Error('stale password config');","typeGuard":null,"tryCatchPattern":"try {\n  await client.connect();\n} catch (err) {\n  if (err instanceof ToolError && err.message.startsWith('ERROR:')) {\n    // daemon rejected auth — refresh CMUX_SOCKET_PASSWORD from the daemon config\n  }\n  throw err;\n}","preventionTips":["Keep CMUX_SOCKET_PASSWORD in sync with the daemon config after rotation","Check the exact ERROR: line in the message — it states why the daemon refused","Confirm you target the daemon instance that owns the configured socket path"],"tags":["auth","socket","handshake"],"backgroundTag":"auth-handshake-rejected","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}