can1357/oh-my-pi · error · ToolError
Missing cmux relay auth metadata for ${endpoint.host}:${endp
Error message
Missing cmux relay auth metadata for ${endpoint.host}:${endpoint.port}; set CMUX_RELAY_ID/CMUX_RELAY_TOKEN or restore ~/.cmux/relay/${endpoint.port}.auth What it means
When the socket path looks like a TCP relay endpoint (127.0.0.1:<port>), the client needs relay credentials: either CMUX_RELAY_ID/CMUX_RELAY_TOKEN env vars or a JSON file ~/.cmux/relay/<port>.auth. If the env vars are absent/invalid and the auth file cannot be read or parsed as JSON, this ToolError is thrown telling you exactly which source to provide.
Source
Thrown at packages/coding-agent/src/tools/browser/cmux/socket-client.ts:203
const port = Number.parseInt(match[2] ?? "", 10);
if (!Number.isInteger(port) || port < 1 || port > 65_535) {
return null;
}
return { host: "127.0.0.1", port };
}
async #loadRelayCredentials(endpoint: RelayEndpoint): Promise<RelayCredentials> {
const environmentCredentials = parseRelayCredentials(this.#relayId, this.#relayToken);
if (environmentCredentials) {
return environmentCredentials;
}
const authPath = path.join(os.homedir(), ".cmux", "relay", `${endpoint.port}.auth`);
let payload: unknown;
try {
payload = await Bun.file(authPath).json();
} catch {
throw new ToolError(
`Missing cmux relay auth metadata for ${endpoint.host}:${endpoint.port}; set CMUX_RELAY_ID/CMUX_RELAY_TOKEN or restore ~/.cmux/relay/${endpoint.port}.auth`,
);
}
const relayId = payload && typeof payload === "object" && "relay_id" in payload ? payload.relay_id : undefined;
const relayToken =
payload && typeof payload === "object" && "relay_token" in payload ? payload.relay_token : undefined;
const fileCredentials = parseRelayCredentials(relayId, relayToken);
if (!fileCredentials) {
throw new ToolError(`Invalid cmux relay auth metadata in ~/.cmux/relay/${endpoint.port}.auth`);
}
return fileCredentials;
}
async #authenticateRelay(endpoint: RelayEndpoint, credentials: RelayCredentials): Promise<void> {
const challengeLine = await this.#nextLine(DEFAULT_CONNECT_TIMEOUT_MS);
let challenge: unknown;
try {
challenge = JSON.parse(challengeLine);View on GitHub (pinned to 9690622007)
Solutions
- Export CMUX_RELAY_ID and CMUX_RELAY_TOKEN (token must be a hex string) before connecting
- Restore or regenerate ~/.cmux/relay/<port>.auth containing relay_id and relay_token (match the current relay port)
- Verify the relay port in the socket path is the currently running relay; a stale port means the wrong .auth filename
Example fix
// before
new CmuxSocketClient({ socketPath: '127.0.0.1:8931' }) // no creds anywhere
// after
export CMUX_RELAY_ID=relay-abc
export CMUX_RELAY_TOKEN=0f1e2d3c4b5a...
new CmuxSocketClient({ socketPath: '127.0.0.1:8931' }) Defensive patterns
Strategy: validation
Validate before calling
const isHex = (s: unknown): s is string =>
typeof s === 'string' && s.trim().length > 0 && s.trim().length % 2 === 0 && /^[0-9a-f]+$/i.test(s.trim());
if (!isHex(process.env.CMUX_RELAY_TOKEN) || !process.env.CMUX_RELAY_ID) {
// check ~/.cmux/relay/<port>.auth exists and is valid JSON before connecting
} Type guard
function hasRelayCredentials(env: NodeJS.ProcessEnv): boolean {
return typeof env.CMUX_RELAY_ID === 'string' && env.CMUX_RELAY_ID.length > 0 &&
typeof env.CMUX_RELAY_TOKEN === 'string' && /^[0-9a-f]+$/i.test(env.CMUX_RELAY_TOKEN.trim()) &&
env.CMUX_RELAY_TOKEN.trim().length % 2 === 0;
} Try / catch
try {
await client.connect();
} catch (err) {
if (err instanceof ToolError && err.message.startsWith('Missing cmux relay auth metadata')) {
// load credentials into env from the relay registration output, then retry once
}
throw err;
} Prevention
- Set CMUX_RELAY_ID/CMUX_RELAY_TOKEN in the environment the agent runs in (cmux injects them natively)
- Keep ~/.cmux/relay/<port>.auth intact — do not clean it with home-dir sweeps
- Re-derive the auth filename after relay port changes
- Validate the token is hex before storing it
When it happens
Trigger: Connecting to a `127.0.0.1:<port>` relay endpoint while CMUX_RELAY_ID/CMUX_RELAY_TOKEN are unset or not a valid id+hex-token pair, and ~/.cmux/relay/<port>.auth is missing, unreadable, or not valid JSON.
Common situations: Running the agent outside the cmux environment where the env vars are normally injected; cmux regenerated the relay port so the old .auth filename no longer matches; home directory differs (containers/CI) so the file is absent.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Invalid cmux relay auth metadata in ~/.cmux/relay/${endpoint
- Invalid cmux relay authentication challenge from ${endpoint.
- Cmux relay authentication failed for ${endpoint.host}:${endp
- Failed to load tree-sitter language: {err}
- cannot stat {0}: No such file or directory
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/364df03230d94fc2.
Report an issue: GitHub.