vercel/ai · error · UnsupportedFunctionalityError

non-streaming transcription with ${this.modelId}

Error message

non-streaming transcription with ${this.modelId}

What it means

Realtime transcription models (detected via isRealtimeTranscriptionModelId, e.g. gpt-4o-transcribe realtime variants) only support streaming output. Calling doGenerate on OpenAITranscriptionModel with such a model id throws UnsupportedFunctionalityError because there is no non-streaming REST endpoint for it.

Source

Thrown at packages/openai/src/transcription/openai-transcription-model.ts:241

            }
          } else {
            formData.append(key, String(value));
          }
        }
      }
    }

    return {
      formData,
      warnings,
    };
  }

  async doGenerate(
    options: OpenAITranscriptionCallOptions,
  ): Promise<Awaited<ReturnType<TranscriptionModelV4['doGenerate']>>> {
    if (isRealtimeTranscriptionModelId(this.modelId)) {
      throw new UnsupportedFunctionalityError({
        functionality: `non-streaming transcription with ${this.modelId}`,
      });
    }

    const currentDate = this.config._internal?.currentDate?.() ?? new Date();
    const { formData, warnings } = await this.getArgs(options);

    const {
      value: response,
      responseHeaders,
      rawValue: rawResponse,
    } = await postFormDataToApi({
      url: this.config.url({
        path: '/audio/transcriptions',
        modelId: this.modelId,
      }),
      headers: combineHeaders(this.config.headers?.(), options.headers),
      formData,

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Use the streaming API (streamTranscription/doStream) with realtime transcription models
  2. Switch the model id to a REST-supported transcription model (e.g. whisper-1, gpt-4o-transcribe) for non-streaming use
  3. Branch your code on the model id to select the right call style

Example fix

// before
await transcribe({ model: openai.transcription('gpt-4o-mini-transcribe-realtime'), audio })
// after
const result = streamTranscribe({ model: openai.transcription('gpt-4o-mini-transcribe-realtime'), audio })
Defensive patterns

Strategy: type-guard

Validate before calling

import { isRealtimeTranscriptionModelId } from '@ai-sdk/openai'; // or local copy
if (isRealtimeTranscriptionModelId(modelId)) {
  // use streaming API instead of transcribe()
}

Type guard

function supportsNonStreamingTranscription(modelId: string): boolean {
  return !isRealtimeTranscriptionModelId(modelId);
}

Try / catch

try {
  result = await transcribe({ model, audio });
} catch (e) {
  if (UnsupportedFunctionalityError.isInstance(e) && e.message.includes('non-streaming transcription')) {
    // switch to the streaming transcription API for this model
  } else throw e;
}

Prevention

When it happens

Trigger: Calling generateText-style transcription (transcribe(...)/doGenerate) with a realtime transcription model id; switching a model id string from a REST transcription model to a realtime one without changing the call to its streaming API.

Common situations: Swapping model ids in config (e.g. 'whisper-1' -> realtime model) while keeping the non-streaming transcribe() call; templated pipelines that always use doGenerate; misunderstanding that realtime models can also do one-shot transcription.

Related errors


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