mastra-ai/mastra · error

Unknown content type: ${(content as any).type}

Error message

Unknown content type: ${(content as any).type}

What it means

toSdkContent maps Mastra multimodal content items to the Voyage SDK shape and supports text, image_url, image_base64, and video_url. Any other content .type hits the default branch and throws, because the Voyage multimodal API has no encoding for it.

Source

Thrown at embedders/voyageai/src/multimodal-embedding.ts:33

  VoyageInputType,
} from './types';

/**
 * Convert our content format to the VoyageAI SDK's content-item shape.
 * The API requires typed objects (never bare strings) inside each input's `content` array.
 */
function toSdkContent(content: VoyageMultimodalContent): Record<string, unknown> {
  switch (content.type) {
    case 'text':
      return { type: 'text', text: content.text };
    case 'image_url':
      return { type: 'image_url', image_url: content.image_url };
    case 'image_base64':
      return { type: 'image_base64', image_base64: content.image_base64 };
    case 'video_url':
      return { type: 'video_url', video_url: content.video_url };
    default:
      throw new Error(`Unknown content type: ${(content as any).type}`);
  }
}

/**
 * Convert a multimodal input to the SDK's input-item shape: an object with a
 * `content` array of typed content objects.
 */
function toSdkInput(input: VoyageMultimodalInput): { content: Record<string, unknown>[] } {
  return { content: input.content.map(toSdkContent) };
}

/**
 * Convert our input type to VoyageAI SDK's expected format
 */
function toSdkInputType(inputType: VoyageInputType | undefined): 'query' | 'document' | undefined {
  if (inputType === null) return undefined;
  return inputType;
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Convert unsupported content types (e.g. audio) to a supported form or remove them from the input.
  2. Check each item's type is exactly one of 'text' | 'image_url' | 'image_base64' | 'video_url' before calling.
  3. Ensure message objects are constructed with the library's content types, not raw external formats.

Example fix

// before
{ type: 'audio_url', audio_url: { url: 'https://...' } }
// after
{ type: 'video_url', video_url: { url: 'https://...' } } // or a supported type
Defensive patterns

Strategy: type-guard

Validate before calling

const SUPPORTED = new Set(['text', 'image_url', 'image_base64', 'video_url']);
for (const item of input) {
  for (const c of item.content) {
    if (!SUPPORTED.has((c as any).type)) {
      throw new Error(`Unsupported Voyage content type: ${(c as any).type}`);
    }
  }
}

Type guard

type VoyageContent = { type: 'text' } | { type: 'image_url'; image_url: unknown } | { type: 'image_base64'; image_base64: unknown } | { type: 'video_url'; video_url: unknown };
function isVoyageContent(c: unknown): c is VoyageContent {
  const t = (c as any)?.type;
  return t === 'text' || t === 'image_url' || t === 'image_base64' || t === 'video_url';
}

Try / catch

try {
  await embedder.embed(input);
} catch (err) {
  if ((err as Error).message.startsWith('Unknown content type:')) {
    console.error('Strip or convert the unsupported item before embedding');
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing a multimodal input containing a content item with an unsupported type value (e.g. 'audio_url', 'file', a mistyped 'ImageUrl', or an undefined type from a malformed message).

Common situations: Building multimodal messages from generic AI SDK content (which includes audio/file types Voyage doesn't accept), misspelling a type literal, or passing untyped objects where type is undefined.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/2c87024b46b1cf89. Report an issue: GitHub.