can1357/oh-my-pi · warning · AbortError

Proxy tunnel aborted

Error message

Proxy tunnel aborted

What it means

connectProxiedSocket tunnels a TLS socket through an HTTP(S) proxy (CONNECT). Before doing any work it checks the caller-supplied AbortSignal and throws AbortError('Proxy tunnel aborted') if the signal is already aborted. This is an intentional cooperative-cancellation guard: the library refuses to start a proxy handshake for an operation that has already been cancelled.

Source

Thrown at packages/ai/src/utils/proxy.ts:286

	/** Caller cancellation for the proxy TCP/TLS handshake and CONNECT tunnel. */
	signal?: AbortSignal;
	/** Maximum wall-clock time to establish the final TLS tunnel. Disabled when absent or non-positive. */
	timeoutMs?: number;
	/** Target TLS profile. Cursor defaults to HTTP/2 when this is absent. */
	tls?: tls.ConnectionOptions;
}

/**
 * Tunnel a socket connection through an HTTP CONNECT proxy.
 * This is used specifically to wrap Node's `http2.connect(baseUrl, { createConnection })` for Cursor.
 */
export async function connectProxiedSocket(
	proxyUrlStr: string,
	targetUrlStr: string,
	options?: ConnectProxiedSocketOptions,
): Promise<tls.TLSSocket> {
	if (options?.signal?.aborted) {
		throw new AbortError("Proxy tunnel aborted");
	}

	const proxyUrl = new URL(proxyUrlStr);
	const targetUrl = new URL(targetUrlStr);

	const useProxySsl = proxyUrl.protocol === "https:";
	const proxyPort = proxyUrl.port ? parseInt(proxyUrl.port, 10) : useProxySsl ? 443 : 80;
	const proxyHost = proxyUrl.hostname;

	const targetPort = targetUrl.port ? parseInt(targetUrl.port, 10) : 443;
	const targetHost = targetUrl.hostname;

	const { promise, resolve, reject } = Promise.withResolvers<tls.TLSSocket>();

	const readyEvent = useProxySsl ? "secureConnect" : "connect";
	let rawSocket: net.Socket | undefined;
	let tunnelSocket: tls.TLSSocket | undefined;
	let timeout: NodeJS.Timeout | undefined;

View on GitHub (pinned to 9690622007)

Solutions

  1. Check `signal?.aborted` before calling connectProxiedSocket and skip the call if already cancelled
  2. Create a fresh AbortController per connection attempt instead of reusing an aborted one
  3. If the abort was unintentional (timeout too aggressive), raise the timeout that triggers controller.abort()
  4. Handle AbortError distinctly from network failures — do not retry it as a transient error; treat as cancellation

Example fix

// before — reusing a possibly-aborted controller
const socket = await connectProxiedSocket(proxyUrl, targetUrl, { signal: controller.signal });
// after — fresh signal per attempt, bail out early
const controller = new AbortController();
setTimeout(() => controller.abort(), timeoutMs);
if (controller.signal.aborted) return;
const socket = await connectProxiedSocket(proxyUrl, targetUrl, { signal: controller.signal });
Defensive patterns

Strategy: try-catch

Validate before calling

if (options?.signal?.aborted) {
  throw new DOMException("Aborted before proxy connect", "AbortError");
}

Type guard

function isAbortError(err: unknown): err is Error {
  return err instanceof Error && (err.name === "AbortError" || err.message.includes("aborted"));
}

Try / catch

try {
  const socket = await connectProxiedSocket(proxy, target, { signal });
} catch (err) {
  if (isAbortError(err)) return; // cancellation, not a failure — do not retry
  throw err;
}

Prevention

When it happens

Trigger: Calling connectProxiedSocket (directly or via provider fetch/socket setup) with options.signal from an AbortController that was already aborted — e.g. a request timeout fired, the user cancelled, or a race where abort happens between controller creation and the call.

Common situations: Request timeouts that abort the controller before the socket connect begins; retry logic that aborts the previous attempt's signal but reuses it for the new attempt; streaming clients cancelled by the consumer while the connection was still being established; global shutdown/dispose aborting all in-flight signals.

Related errors


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