can1357/oh-my-pi · error · ToolError

line

Error message

line

What it means

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.

Source

Thrown at packages/coding-agent/src/tools/browser/cmux/socket-client.ts:162

		const socket = relayEndpoint
			? net.createConnection({ host: relayEndpoint.host, port: relayEndpoint.port })
			: net.createConnection({ path: this.#socketPath });
		this.#socket = socket;
		this.#buffer = "";
		socket.setEncoding("utf8");
		socket.on("data", chunk => this.#onData(String(chunk)));
		socket.on("error", err => this.#handleSocketFailure(err));
		socket.on("close", () => this.#handleSocketClose());

		try {
			await this.#waitForConnect(socket);
			if (relayEndpoint && relayCredentials) {
				await this.#authenticateRelay(relayEndpoint, relayCredentials);
			}
			if (this.#password) {
				const line = await this.#sendLine(`auth ${this.#password}`, DEFAULT_CONNECT_TIMEOUT_MS);
				if (line.startsWith("ERROR:") && !line.includes("Unknown command 'auth'")) {
					throw new ToolError(line);
				}
			}
			this.#connected = true;
		} catch (err) {
			this.#connected = false;
			socket.destroy();
			if (err instanceof ToolError) throw err;
			throw new ToolError(
				`Failed to connect to cmux socket at ${this.#socketPath}: ${err instanceof Error ? err.message : String(err)}`,
			);
		}
	}

	#parseRelayEndpoint(): RelayEndpoint | null {
		const value = this.#socketPath.trim();
		if (value.length === 0 || value.startsWith("/")) {
			return null;
		}

View on GitHub (pinned to 9690622007)

Solutions

  1. Correct the password (CMUX_SOCKET_PASSWORD env or the password option) to match the running cmux daemon
  2. Verify which daemon instance owns the socket path and its current credentials
  3. If the daemon genuinely has no auth, unset the password — but check the ERROR line first, since 'Unknown command auth' is tolerated automatically

Example fix

// before
export CMUX_SOCKET_PASSWORD=old-secret
// after
export CMUX_SOCKET_PASSWORD=$(cat ~/.cmux/socket.password)
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the password source before connecting
const password = process.env.CMUX_SOCKET_PASSWORD;
if (password && !fs.existsSync(passwordFile)) throw new Error('stale password config');

Try / catch

try {
  await client.connect();
} catch (err) {
  if (err instanceof ToolError && err.message.startsWith('ERROR:')) {
    // daemon rejected auth — refresh CMUX_SOCKET_PASSWORD from the daemon config
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/66ad7f2a6aba411d. Report an issue: GitHub.