{"record":{"id":"018a3038663a39ca","repo":"can1357/oh-my-pi","slug":"invalid-cmux-relay-auth-metadata-in-cmux-relay","errorCode":null,"errorMessage":"Invalid cmux relay auth metadata in ~/.cmux/relay/${endpoint.port}.auth","messagePattern":"Invalid cmux relay auth metadata in ~/\\.cmux/relay/(.+?)\\.auth","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/cmux/socket-client.ts","lineNumber":212,"sourceCode":"\t\tif (environmentCredentials) {\n\t\t\treturn environmentCredentials;\n\t\t}\n\n\t\tconst authPath = path.join(os.homedir(), \".cmux\", \"relay\", `${endpoint.port}.auth`);\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await Bun.file(authPath).json();\n\t\t} catch {\n\t\t\tthrow new ToolError(\n\t\t\t\t`Missing cmux relay auth metadata for ${endpoint.host}:${endpoint.port}; set CMUX_RELAY_ID/CMUX_RELAY_TOKEN or restore ~/.cmux/relay/${endpoint.port}.auth`,\n\t\t\t);\n\t\t}\n\t\tconst relayId = payload && typeof payload === \"object\" && \"relay_id\" in payload ? payload.relay_id : undefined;\n\t\tconst relayToken =\n\t\t\tpayload && typeof payload === \"object\" && \"relay_token\" in payload ? payload.relay_token : undefined;\n\t\tconst fileCredentials = parseRelayCredentials(relayId, relayToken);\n\t\tif (!fileCredentials) {\n\t\t\tthrow new ToolError(`Invalid cmux relay auth metadata in ~/.cmux/relay/${endpoint.port}.auth`);\n\t\t}\n\t\treturn fileCredentials;\n\t}\n\n\tasync #authenticateRelay(endpoint: RelayEndpoint, credentials: RelayCredentials): Promise<void> {\n\t\tconst challengeLine = await this.#nextLine(DEFAULT_CONNECT_TIMEOUT_MS);\n\t\tlet challenge: unknown;\n\t\ttry {\n\t\t\tchallenge = JSON.parse(challengeLine);\n\t\t} catch {\n\t\t\tthrow new ToolError(`Invalid cmux relay authentication challenge from ${endpoint.host}:${endpoint.port}`);\n\t\t}\n\t\tif (\n\t\t\t!challenge ||\n\t\t\ttypeof challenge !== \"object\" ||\n\t\t\t!(\"protocol\" in challenge) ||\n\t\t\tchallenge.protocol !== \"cmux-relay-auth\" ||\n\t\t\t!(\"version\" in challenge) ||","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/cmux/socket-client.ts#L194-L230","documentation":"The relay auth file ~/.cmux/relay/<port>.auth was readable and valid JSON, but its relay_id/relay_token fields failed parseRelayCredentials: both must be non-empty strings and the token must be an even-length hex string. The client refuses to attempt HMAC auth with malformed credentials.","triggerScenarios":"The .auth file exists but contains missing/empty relay_id or relay_token, a non-hex token (e.g. base64 or raw secret), an odd-length hex token, or wrong JSON field names (not relay_id/relay_token).","commonSituations":"Hand-edited or truncated .auth file; token pasted in base64 rather than hex; cmux version that wrote a different schema than the client expects; copy-paste dropped characters from the token.","solutions":["Fix the .auth file so relay_id is a non-empty string and relay_token is a non-empty even-length hex string","Prefer setting CMUX_RELAY_ID/CMUX_RELAY_TOKEN env vars instead — env credentials take precedence over the file","Regenerate the file from cmux rather than hand-editing it"],"exampleFix":"// before (~/.cmux/relay/8931.auth)\n{ \"relay_id\": \"relay-abc\", \"relay_token\": \"c28tZS10b2tlbg==\" }\n// after (token as hex)\n{ \"relay_id\": \"relay-abc\", \"relay_token\": \"736f6d652d746f6b656e\" }","handlingStrategy":"validation","validationCode":"const auth = JSON.parse(await Bun.file(authPath).text());\nconst ok = typeof auth.relay_id === 'string' && auth.relay_id.length > 0 &&\n  typeof auth.relay_token === 'string' && /^[0-9a-f]+$/.test(auth.relay_token) &&\n  auth.relay_token.length % 2 === 0;\nif (!ok) throw new Error('malformed relay auth file — regenerate from cmux');","typeGuard":"function isRelayAuthPayload(v: unknown): v is { relay_id: string; relay_token: string } {\n  if (typeof v !== 'object' || v === null) return false;\n  const o = v as Record<string, unknown>;\n  return typeof o.relay_id === 'string' && o.relay_id.length > 0 &&\n    typeof o.relay_token === 'string' && o.relay_token.length > 0 &&\n    o.relay_token.length % 2 === 0 && /^[0-9a-f]+$/i.test(o.relay_token);\n}","tryCatchPattern":"try {\n  await client.connect();\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes('Invalid cmux relay auth metadata')) {\n    // regenerate ~/.cmux/relay/<port>.auth via cmux, or switch to env credentials\n  }\n  throw err;\n}","preventionTips":["Never hand-edit the .auth file; regenerate it from cmux","Store the token as hex, not base64 or raw bytes","Prefer CMUX_RELAY_ID/CMUX_RELAY_TOKEN env vars, which bypass the file entirely","Validate field names are exactly relay_id and relay_token"],"tags":["auth","validation","relay","config"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}