can1357/oh-my-pi · info
Daemon broker request aborted
Error message
Daemon broker request aborted
What it means
request() rejects immediately if the caller-supplied AbortSignal is already aborted, before attempting a connection. This signals that the operation was cancelled before it started, so no RPC is sent and no socket is opened.
Source
Thrown at packages/coding-agent/src/launch/client.ts:165
readonly #inFlightCompletionIds = new Set<string>();
readonly #completionSubscriptionId = crypto.randomUUID();
#socket: net.Socket | undefined;
#connectPromise: Promise<void> | undefined;
#buffer = "";
#closed = false;
#completionReconnectTimer: NodeJS.Timeout | undefined;
constructor(projectDir: string, runtimeDir: string, token: string, options: DaemonBrokerClientOptions) {
this.projectDir = projectDir;
this.#runtimeDir = runtimeDir;
this.#endpoint = daemonBrokerEndpoint(projectDir, runtimeDir);
this.#token = token;
this.#idleGraceMs = options.idleGraceMs;
}
async request(operation: DaemonOperation, signal?: AbortSignal): Promise<DaemonRpcResult> {
if (this.#closed) throw new Error("Daemon broker client is closed");
if (signal?.aborted) throw new Error("Daemon broker request aborted");
await this.#connect();
const socket = this.#socket;
if (!socket || socket.destroyed) throw new Error("Daemon broker socket is unavailable");
const completionUnsubscribes = [...this.#completionUnsubscribes];
const completionReplays = [...this.#completionReplays];
const id = crypto.randomUUID();
const { promise, resolve, reject } = Promise.withResolvers<DaemonRpcResult>();
const timer = setTimeout(() => {
const pending = this.#pending.get(id);
if (!pending) return;
this.#pending.delete(id);
pending.removeAbort?.();
reject(new Error(`Daemon ${operation.op} request timed out`));
}, requestTimeoutMs(operation));
const pending: PendingRequest = { operation, resolve, reject, timer };
if (signal) {
const abort = (): void => {View on GitHub (pinned to 9690622007)
Solutions
- Check signal.aborted before calling request and skip the call gracefully
- Create a fresh AbortController per request rather than sharing one across a sequence
- Handle AbortError-style failures in callers of #publishCompletionOwners so cancellation is expected, not exceptional
Example fix
// before await client.request(op, signal); // after if (signal?.aborted) return; await client.request(op, signal);
Defensive patterns
Strategy: validation
Validate before calling
if (signal?.aborted) return; // or throw a typed cancellation before calling request
Try / catch
try {
await client.request(op, signal);
} catch (err) {
if (err.message === 'Daemon broker request aborted') return; // expected cancellation, not a failure
throw err;
} Prevention
- Use a fresh AbortController per logical request instead of sharing one
- Check signal.aborted at each await boundary in multi-step flows
- Treat aborted-signal errors as control flow, not faults
When it happens
Trigger: Passing an AbortSignal that was aborted earlier (e.g. a timeout that fired during prior awaits, or a user cancellation) into DaemonBrokerClient.request().
Common situations: Racing request timeouts; user cancels an action whose completion publish still runs; reusing one AbortController for a whole batch after one item failed.
Related errors
- Request was aborted
- Auth broker request aborted
- OAuth refresh ownership aborted by caller
- Request was aborted.
- AbortError
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ead2e88c2d3e9441.
Report an issue: GitHub.