microsoft/aspire · error · AbortError

The operation was aborted before it was sent to the AppHost.

Error message

The operation was aborted before it was sent to the AppHost.

What it means

When an operation is called with an AbortSignal/abort token, the transport first checks whether the signal is already aborted before registering cancellation with the AppHost. If it is, the operation can never meaningfully start, so registerCancellation throws immediately instead of sending a doomed request. This is an early-exit guard, not a timeout.

Solutions

  1. Check `signal.aborted` before invoking and skip the call entirely if already aborted.
  2. Create a fresh AbortController per operation instead of reusing an aborted signal.
  3. If abort-before-call is expected, catch the error and treat it as a no-op/cancelled result.
  4. Only abort signals after the operation has been initiated if you want mid-flight cancellation (handled by a different path).

Example fix

// before
const controller = new AbortController();
controller.abort();
await client.capability('build', { signal: controller.signal }); // throws

// after
const controller = new AbortController();
if (!controller.signal.aborted) {
  await client.capability('build', { signal: controller.signal });
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (signal?.aborted) {
  return; // skip the call entirely — it can never be sent
}

Type guard

const isLiveSignal = (s?: AbortSignal): s is AbortSignal => s instanceof AbortSignal && !s.aborted;

Try / catch

try {
  await client.capability('build', { signal });
} catch (e) {
  if (String((e as Error).message).includes('aborted before it was sent')) {
    return; // treat as cancelled no-op, not a failure
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing an AbortSignal (or cancellation token) that is already aborted to a transport operation, e.g. `client.op(args, { signal: controller.signal })` after `controller.abort()` was called, or reusing a signal from an already-completed/aborted request.

Common situations: A request scope was cancelled upstream (HTTP request aborted, user navigated away) before the AppHost call was made; a shared CancellationTokenSource aborted by an earlier failure; racing user cancellation with the call setup.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/c5fa28f70f9ba95e. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/transport.mts:652

): string | undefined {
    const client = isAspireClientLike(clientOrSignalOrToken) ? clientOrSignalOrToken : undefined;
    const signalOrToken = client
        ? maybeSignalOrToken
        : clientOrSignalOrToken as AbortSignal | CancellationToken | undefined;

    if (!signalOrToken) {
        return undefined;
    }

    if (isCancellationTokenLike(signalOrToken)) {
        return signalOrToken.register(client);
    }

    const signal = signalOrToken;
    const cancellationClient = resolveCancellationClient(client);

    if (signal.aborted) {
        throw createAbortError('The operation was aborted before it was sent to the AppHost.');
    }

    const cancellationId = `ct_${++cancellationIdCounter}_${Date.now()}`;

    // Set up the abort listener
    const onAbort = () => {
        // Send cancel request to host
        if (cancellationClient.connected) {
            cancellationClient.cancelToken(cancellationId).catch(() => {
                // Ignore errors - the operation may have already completed
            });
        }
        // Clean up the listener
        cancellationRegistry.delete(cancellationId);
    };

    // Listen for abort
    signal.addEventListener('abort', onAbort, { once: true });

View on GitHub (pinned to 25830f84bd)