vercel/ai · warning
ACP connection closed before cancellation.
Error message
ACP connection closed before cancellation.
What it means
In the cancel path of runTurn, if the ACP connection object is already null (the agent connection closed), the bridge cannot send the session/cancel notification and throws this Error. The throw is caught immediately and recorded as cancellationFailureError, so it signals that cancellation could not be delivered to the agent rather than crashing the turn outright.
Source
Thrown at packages/harness-acp/src/v1/bridge/index.ts:238
sessionId: activeSession.sessionId,
model: start.model,
mapping: start.modelMapping,
});
let rejectCancellationFailure!: (error: unknown) => void;
const cancellationFailure = new Promise<never>((_, reject) => {
rejectCancellationFailure = reject;
});
void cancellationFailure.catch(() => {});
let cancellationRequested = false;
let cancellationFailureError: Error | undefined;
const cancel = async () => {
if (cancellationRequested) return;
cancellationRequested = true;
activePermissionController?.cancelAll();
try {
if (connection == null) {
throw new Error('ACP connection closed before cancellation.');
}
await connection.agent.notify(acp.methods.agent.session.cancel, {
sessionId: activeSession.sessionId,
});
} catch (error) {
cancellationFailureError = createACPBridgeError({
stage: 'session cancellation',
cause: error,
});
rejectCancellationFailure(cancellationFailureError);
}
};
turn.emit({ type: 'stream-start' });
const emitStreamEvent = createEmitStreamEvent({
emit: event => turn.emit(event as BridgeEvent),
emitToolCallCandidate: ({ toolCall }) => {
turn.emit({
type: 'acp-tool-call-candidate',View on GitHub (pinned to 69428b1f8b)
Solutions
- Treat this as a benign race when the connection is already closed — the turn is over, so cancellation delivery is moot.
- Check agent stderr/logs to determine why the connection closed prematurely if cancellations routinely fail this way.
- Add application-level guard so cancellation is only requested while a turn is known to be active.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await bridge.runTurn({ prompt, abortSignal });
} catch (error) {
if (error instanceof Error && error.message === 'ACP connection closed before cancellation.') {
// benign: agent already disconnected; inspect logs if it happens often
return;
}
throw error;
} Prevention
- Check agent process health if cancellations frequently race with connection closure.
- Only request cancellation while a turn is known to be active.
- Capture agent stderr to diagnose premature connection drops.
When it happens
Trigger: cancel() is invoked (e.g. by an abort signal or turn teardown) after the ACP agent process/connection has already terminated, so connection == null when attempting connection.agent.notify(acp.methods.agent.session.cancel, ...).
Common situations: User aborts the request at the same moment the agent process crashes or exits; the agent already finished/closed the connection before the abort signal fired; timeout logic cancels a turn whose connection already dropped.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- ${harnessId} ACP cold restoration completed without identify
- The ${model.provider} model "${model.modelId}" does not supp
- Invalid argument for parameter requests: requests must not b
- Invalid argument for parameter requests: request IDs must no
- Invalid argument for parameter requests: request IDs must be
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/9b023214e9c1a110.
Report an issue: GitHub.