can1357/oh-my-pi · error · Error
Unexpected broker response ${next.op}
Error message
Unexpected broker response ${next.op} What it means
In follow mode `runLogs` polls the broker with `{op:"logs", follow:true, cursor}` and expects each reply to be a logs response carrying new `text` and a `cursor`. This guard throws when a follow-poll reply has a different op — the loop would otherwise read `next.text`/`next.cursor` on a foreign response shape.
Source
Thrown at packages/coding-agent/src/cli/ps-cli.ts:253
}
const initial = first.text.replace(/\n$/, "").split("\n").slice(-lines).join("\n");
if (initial) process.stdout.write(`${initial}\n`);
let previous = first.text;
let cursor = first.cursor;
let state = first.state;
while (!TERMINAL_STATES[state]) {
const next = await client.request({
op: "logs",
name,
lines: 1_000,
head: false,
grep: cmd.flags.grep,
follow: true,
cursor,
renderTerminalRows: false,
timeoutMs: 30_000,
});
if (next.op !== "logs") throw new Error(`Unexpected broker response ${next.op}`);
// The broker always returns the tail window (cursor is only a wait
// watermark), so trim the part we already printed.
const fresh = next.text.slice(overlapLength(previous, next.text));
if (fresh) process.stdout.write(fresh.endsWith("\n") ? fresh : `${fresh}\n`);
previous = next.text;
cursor = next.cursor;
state = next.state;
}
console.log(chalk.dim(`[${name}: ${state}]`));
}
/** Longest suffix of `previous` that is a prefix of `next` — the already-printed portion of a tail window. */
function overlapLength(previous: string, next: string): number {
for (let k = Math.min(previous.length, next.length); k > 0; k--) {
const offset = previous.length - k;
let match = true;
for (let i = 0; i < k; i++) {
if (previous.charCodeAt(offset + i) !== next.charCodeAt(i)) {View on GitHub (pinned to 9690622007)
Solutions
- Re-run `omp ps logs --follow` after confirming the daemon still exists in `omp ps --all`.
- Check the broker process is alive and from the same omp version as the CLI; restart the broker if it was upgraded mid-session.
- Wrap the follow loop's request in a catch that exits the poll loop cleanly on error ops instead of treating every reply as logs.
Example fix
// before
const next = await client.request({ op: "logs", name, follow: true, cursor, ... });
if (next.op !== "logs") throw new Error(`Unexpected broker response ${next.op}`);
// after
const next = await client.request({ op: "logs", name, follow: true, cursor, ... });
if (next.op === "error") break; // daemon gone; end follow cleanly
if (next.op !== "logs") throw new Error(`Unexpected broker response ${next.op}`); Defensive patterns
Strategy: try-catch
Validate before calling
if (previous === undefined && !(await client.request({ op: "list" }).then(r => r.op === "list" && r.daemons.some(d => d.name === name)))) {
throw new Error(`Daemon "${name}" not found; follow aborted`);
} Type guard
function isLogsResponse(r: { op: string }): r is { op: "logs"; text: string; cursor: string; state: string } {
return r.op === "logs";
} Try / catch
try {
while (following) {
const next = await client.request({ op: "logs", name, follow: true, cursor });
if (!isLogsResponse(next)) break; // end follow cleanly on foreign/error replies
/* print fresh text */
cursor = next.cursor;
}
} catch (err) {
console.error(chalk.red(`follow ended: ${err instanceof Error ? err.message : String(err)}`));
} Prevention
- Exit follow loops gracefully on non-logs replies instead of throwing mid-stream.
- Re-verify the daemon still exists before long follow sessions.
- Expect brokers to restart during upgrades; re-issue follow after detecting a protocol change.
When it happens
Trigger: A `--follow` logs session where an intermediate `client.request({op:"logs", follow:true, cursor, ...})` resolves with a non-"logs" op — typically the broker switching to an error response mid-stream (daemon removed, broker shutting down) or a protocol version change.
Common situations: Following logs while the daemon is stopped/removed underneath the stream; the broker dies or is upgraded mid-follow and the revived broker speaks a different protocol; long-running follow sessions crossing an omp upgrade.
Related errors
- Unexpected broker response ${first.op}
- Unexpected broker response ${result.op}
- Unexpected broker response ${result.op}
- Unexpected response ${result.op}
- Timed out waiting for agent_end. Stderr: {self.stderr}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/dd95ce2f7aa2f833.
Report an issue: GitHub.