vercel/ai · error · NoSuchModelError

Fish Audio does not provide embedding models

Error message

Fish Audio does not provide embedding models

What it means

The Fish Audio provider's `embeddingModel` (and its alias `textEmbeddingModel`) always throws `NoSuchModelError` because Fish Audio offers no embedding capability. This stub exists to satisfy the ProviderV4 interface while giving callers a clear explanation.

Source

Thrown at packages/fish-audio/src/fish-audio-provider.ts:141

  };

  provider.specificationVersion = 'v4' as const;
  provider.speech = createSpeechModel;
  provider.speechModel = createSpeechModel;
  provider.transcription = createTranscriptionModel;
  provider.transcriptionModel = createTranscriptionModel;

  // Required ProviderV4 methods that are not supported
  provider.languageModel = (modelId: string) => {
    throw new NoSuchModelError({
      modelId,
      modelType: 'languageModel',
      message: 'Fish Audio does not provide language models',
    });
  };

  provider.embeddingModel = (modelId: string) => {
    throw new NoSuchModelError({
      modelId,
      modelType: 'embeddingModel',
      message: 'Fish Audio does not provide embedding models',
    });
  };
  provider.textEmbeddingModel = provider.embeddingModel;

  provider.imageModel = (modelId: string) => {
    throw new NoSuchModelError({
      modelId,
      modelType: 'imageModel',
      message: 'Fish Audio does not provide image models',
    });
  };

  return provider as FishAudioProvider;
}

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Use an embedding-capable provider (e.g. @ai-sdk/openai, @ai-sdk/amazon-bedrock) for embed/embedMany
  2. Restrict fishAudio usage to speech and transcription features
  3. Add capability checks before dynamically choosing a provider for embeddings

Example fix

// before
const model = fishAudio.textEmbeddingModel('default');
await embed({ model, value: 'text' });
// after
const model = openai.textEmbeddingModel('text-embedding-3-small');
await embed({ model, value: 'text' });
Defensive patterns

Strategy: validation

Validate before calling

// never route embed/embedMany to fishAudio; keep an allowlist of embedding providers
const EMBEDDING_PROVIDERS = new Set(['openai', 'amazon-bedrock', 'google', 'mistral']);
if (!EMBEDDING_PROVIDERS.has(providerName)) throw new Error(`${providerName} does not support embeddings`);

Type guard

function isNoSuchModelError(e: unknown): e is NoSuchModelError {
  return NoSuchModelError.isInstance(e);
}

Try / catch

try {
  return await embed({ model: fishAudio.textEmbeddingModel('x'), value });
} catch (e) {
  if (NoSuchModelError.isInstance(e) && e.modelType === 'embeddingModel') {
    return embed({ model: openai.textEmbeddingModel('text-embedding-3-small'), value });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `fishAudio.embeddingModel('id')`, `fishAudio.textEmbeddingModel('id')`, or passing the fishAudio provider to embed/embedMany.

Common situations: Building a provider-agnostic embed pipeline and substituting fishAudio; assuming all AI SDK providers support embeddings; dynamic provider selection that doesn't check capabilities.

Related errors


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