vercel/ai · warning · MCPClientError
MCP client initialization was aborted
Error message
MCP client initialization was aborted
What it means
Thrown in the init catch path when the external AbortSignal passed to createMCPClient was aborted during initialization. The client re-wraps the abort as MCPClientError with the signal's reason as cause, after the transport is closed.
Source
Thrown at packages/mcp/src/tool/mcp-client.ts:595
{
method: 'notifications/initialized',
},
{ signal },
);
return this;
} catch (error) {
try {
await waitForAbort(this.transport.close({ signal }), signal);
} catch {}
this.onClose();
if (timeoutError != null) {
throw timeoutError;
}
if (externalSignal?.aborted) {
throw new MCPClientError({
message: 'MCP client initialization was aborted',
cause: externalSignal.reason,
});
}
throw error;
} finally {
if (timeoutId != null) {
clearTimeout(timeoutId);
}
}
}
private async tryProtocolDiscovery(
signal: AbortSignal | undefined,
): Promise<boolean> {
this.protocolEra = 'modern';
this.protocolVersion = LATEST_PROTOCOL_VERSION;View on GitHub (pinned to 69428b1f8b)
Solutions
- Catch MCPClientError and treat message 'MCP client initialization was aborted' as an expected cancellation, not a server failure.
- Increase the timeout if the abort is from your own deadline and the server is slow to initialize.
- Check error.cause (the signal reason) to identify who aborted.
- Avoid aborting the signal during setup, or retry creation after the abort reason is resolved.
Example fix
// before
const client = await createMCPClient({ transport, signal: controller.signal });
// after
try {
const client = await createMCPClient({ transport, signal: controller.signal });
} catch (e) {
if (MCPClientError.isInstance(e) && e.message.includes('aborted')) return; // expected cancellation
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (controller.signal.aborted) {
return; // do not start client creation with an already-aborted signal
} Type guard
function isAbortError(e: unknown): boolean {
return e instanceof Error && (e.name === 'AbortError' || e.message.includes('aborted'));
} Try / catch
try {
const client = await createMCPClient({ transport, signal: controller.signal });
} catch (e) {
if (MCPClientError.isInstance(e) && e.message === 'MCP client initialization was aborted') {
return; // expected cancellation, use e.cause to see why
}
throw e;
} Prevention
- Don't abort the signal during client setup unless cancellation is intended
- Give initialization a generous timeout if servers start slowly
- Check e.cause to distinguish user cancellation from timeouts
When it happens
Trigger: Caller-supplied AbortSignal fires while the initialize handshake/discovery request is in flight; e.g. a request timeout, user navigation, or explicit abortController.abort() during client creation.
Common situations: React effect cleanups aborting in-flight client creation; server taking longer than a caller-imposed timeout; user navigating away; request cancellations in serverless functions.
Related errors
- Stream aborted
- Transcription request was aborted
- AbortError
- The ACP implementation did not load the active harness-owned
- AbortError
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/6bcd4d42337c9ff4.
Report an issue: GitHub.