{"record":{"id":"2e0914a35f04a366","repo":"can1357/oh-my-pi","slug":"formatcmuxerror-response-error","errorCode":null,"errorMessage":"formatCmuxError(response.error)","messagePattern":"formatCmuxError\\(response\\.error\\)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/cmux/socket-client.ts","lineNumber":401,"sourceCode":"\t#parseResponse(line: string): Record<string, unknown> {\n\t\tif (line.startsWith(\"ERROR:\")) {\n\t\t\tthrow new ToolError(line);\n\t\t}\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = JSON.parse(line);\n\t\t} catch (err) {\n\t\t\tthrow new ToolError(`Invalid cmux socket JSON response: ${err instanceof Error ? err.message : String(err)}`);\n\t\t}\n\t\tif (!payload || typeof payload !== \"object\") {\n\t\t\tthrow new ToolError(\"Invalid cmux socket response: expected object\");\n\t\t}\n\t\tconst response = payload as { ok?: unknown; result?: unknown; error?: CmuxErrorPayload };\n\t\tif (response.ok === true) {\n\t\t\treturn (response.result ?? {}) as Record<string, unknown>;\n\t\t}\n\t\tif (response.ok === false) {\n\t\t\tthrow new ToolError(formatCmuxError(response.error));\n\t\t}\n\t\tthrow new ToolError(\"Invalid cmux socket response: missing ok flag\");\n\t}\n\n\t#handleSocketFailure(err: Error): void {\n\t\tif (this.#disposed) return;\n\t\tthis.#connected = false;\n\t\tthis.#connectPromise = null;\n\t\tthis.#rejectAll(new ToolError(`cmux socket error: ${err.message}`));\n\t\tthis.#socket?.destroy();\n\t\tthis.#socket = null;\n\t}\n\n\t#handleSocketClose(): void {\n\t\tconst hadPendingRead = this.#lineWaiters.length > 0;\n\t\tthis.#connected = false;\n\t\tthis.#connectPromise = null;\n\t\tthis.#socket = null;","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/cmux/socket-client.ts#L383-L419","documentation":"When the response envelope has ok === false, the request itself failed on the cmux server side; #parseResponse throws a ToolError whose message is formatCmuxError(response.error) — i.e. '<code>: <message>[ details=<json>]'. This is the daemon's structured application-level error, faithfully surfaced to the caller.","triggerScenarios":"Any cmux request the daemon completes with ok:false: invalid params, target/tab not found, navigation failure, permission denied, internal daemon error. The thrown message equals the server's error code/message/details.","commonSituations":"Requesting a tab id that no longer exists; navigating to an unreachable URL; daemon-side validation rejecting params; relay authorized but command not permitted.","solutions":["Parse the code/message in the thrown text and fix the request accordingly (bad id, bad URL, bad params)","Check whether the referenced resource (tab, session) still exists and re-list before acting","Inspect daemon logs for the matching error code if the message is opaque","Retry transient codes (timeouts, busy) with backoff"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await client.request(method, params);\n} catch (err) {\n  if (err instanceof ToolError) {\n    const m = /^(\\w[\\w.-]*):\\s(.+?)(?: details=(.*))?$/s.exec(err.message);\n    if (m) {\n      const [, code, message, details] = m;\n      // branch on code: retry transient codes, re-list resources for not-found, surface the rest\n    }\n  }\n  throw err;\n}","preventionTips":["Re-list tabs/resources immediately before acting on ids — they can disappear between calls","Validate params against the daemon's expected schema before sending","Implement backoff retry only for codes known to be transient (timeout/busy)"],"tags":["server-error","rpc","application-error"],"backgroundTag":"rpc-remote-error","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}