vercel/ai · info

Transcription request was aborted

Error message

Transcription request was aborted

What it means

AssemblyAI transcription polling loop checks the caller-supplied abortSignal before each status-polling GET. If the signal is already aborted, it throws this generic Error instead of continuing to poll. It exists so callers can cancel long-running transcription waits (which can take minutes).

Source

Thrown at packages/assemblyai/src/assemblyai-transcription-model.ts:286

  private async waitForCompletion(
    transcriptId: string,
    headers: Record<string, string | undefined> | undefined,
    abortSignal?: AbortSignal,
  ): Promise<{
    transcript: z.infer<typeof assemblyaiTranscriptionResponseSchema>;
    rawTranscript: unknown;
    responseHeaders: Record<string, string>;
  }> {
    const pollingInterval =
      this.config.pollingInterval ?? this.POLLING_INTERVAL_MS;

    // Honor a caller-provided fetch (proxy, auth injection, tests) for the
    // polling GETs, matching the upload/submit calls that use config.fetch.
    const fetchImpl = this.config.fetch ?? globalThis.fetch;

    while (true) {
      if (abortSignal?.aborted) {
        throw new Error('Transcription request was aborted');
      }

      const response = await fetchImpl(
        this.config.url({
          path: `/v2/transcript/${transcriptId}`,
          modelId: this.modelId,
        }),
        {
          method: 'GET',
          headers: combineHeaders(
            this.config.headers?.(),
            headers,
          ) as HeadersInit,
          signal: abortSignal,
        },
      );

      if (!response.ok) {

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Pass a fresh AbortController signal only if you actually want cancellation.
  2. Check signal.aborted before calling and skip transcription if already aborted.
  3. Wrap the call in try/catch and treat this error as an intentional cancel, not a failure.
  4. Increase or remove upstream timeouts that abort the shared signal prematurely.

Example fix

// before
const result = await model.transcript({ transcriptId, abortSignal: controller.signal });
// after
try {
  const result = await model.transcript({ transcriptId, abortSignal: controller.signal });
} catch (e) {
  if (controller.signal.aborted) return; // intentional cancellation
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (abortSignal?.aborted) {
  // skip the transcription call entirely
  return;
}

Try / catch

try {
  await model.transcript({ transcriptId, abortSignal });
} catch (e) {
  if (abortSignal?.aborted || (e instanceof Error && e.message === 'Transcription request was aborted')) {
    return; // treat as cancellation
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling transcript()/rawTranscript() on assemblyai.transcriptionModel with an abortSignal that becomes (or already is) aborted while waitForCompletion polls GET /v2/transcript/{id}.

Common situations: User cancels a UI request mid-transcription; server request shutdown triggers AbortController; a shared signal aborted by an earlier timeout is reused.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/7295bfc0819ddb26. Report an issue: GitHub.