vercel/ai · error · AISDKError

TranscriptionJobSubmissionFailed

TranscriptionJobSubmissionFailed

Error message

Failed to submit transcription job to Rev.ai

What it means

This error is thrown by revai-transcription-model.doGenerate when the HTTP response from Rev.ai's job-submission endpoint reports a failed status. It wraps the full submission response as the cause, so the underlying Rev.ai error detail is preserved. It means the transcription job was never accepted by Rev.ai.

Source

Thrown at packages/revai/src/revai-transcription-model.ts:161

    const { formData, warnings } = await this.getArgs(options);

    const { value: submissionResponse } = await postFormDataToApi({
      url: this.config.url({
        path: '/speechtotext/v1/jobs',
        modelId: this.modelId,
      }),
      headers: combineHeaders(this.config.headers?.(), options.headers),
      formData,
      failedResponseHandler: revaiFailedResponseHandler,
      successfulResponseHandler: createJsonResponseHandler(
        revaiTranscriptionJobResponseSchema,
      ),
      abortSignal: options.abortSignal,
      fetch: this.config.fetch,
    });

    if (submissionResponse.status === 'failed') {
      throw new AISDKError({
        message: 'Failed to submit transcription job to Rev.ai',
        name: 'TranscriptionJobSubmissionFailed',
        cause: submissionResponse,
      });
    }

    const jobId = submissionResponse.id;
    const timeoutMs = 60 * 1000; // 60 seconds timeout
    const startTime = Date.now();
    const pollingInterval = 1000;
    let jobResponse = submissionResponse;

    while (jobResponse.status !== 'transcribed') {
      // Check if we've exceeded the timeout
      if (Date.now() - startTime > timeoutMs) {
        throw new AISDKError({
          message: 'Transcription job polling timed out',
          name: 'TranscriptionJobPollingTimedOut',

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Inspect error.cause (the raw submission response) for Rev.ai's detailed failure reason
  2. Verify the REV_AI_API_KEY is valid and has quota
  3. Check the media URL/file is publicly reachable and in a supported format
  4. Retry on transient failures with backoff

Example fix

// before
await revai.transcriptionModel('general').doGenerate({ mediaUrl: 'https://private/file.mp3' });
// after
// expose the file publicly or upload bytes, and catch:
try { await model.doGenerate(opts); } catch (e) { console.error(e.cause); }
Defensive patterns

Strategy: try-catch

Validate before calling

if (!process.env.REV_AI_API_KEY) throw new Error('REV_AI_API_KEY is not set');
const ok = await fetch(mediaUrl, { method: 'HEAD' }).then(r => r.ok).catch(() => false);
if (!ok) throw new Error('Media URL is not reachable');

Type guard

function isTranscriptionJobSubmissionFailed(e) {
  return typeof e === 'object' && e !== null && e.name === 'TranscriptionJobSubmissionFailed';
}

Try / catch

try {
  const result = await model.doGenerate(options);
} catch (e) {
  if (e.name === 'TranscriptionJobSubmissionFailed') {
    console.error('Rev.ai submission failed:', e.cause);
  } else throw e;
}

Prevention

When it happens

Trigger: POST to Rev.ai's transcription endpoint returns submissionResponse.status === 'failed' — e.g. invalid API key, malformed media URL, unsupported file format, or payload rejected by Rev.ai.

Common situations: Expired or missing REV_AI_API_KEY, media file unreachable or in an unsupported codec, exceeding account quotas, transient Rev.ai API outages.

Related errors


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