vercel/ai · error · InvalidPromptError

DeepSeek `fileData` image parts require inline data, not a U

Error message

DeepSeek `fileData` image parts require inline data, not a URL.

What it means

When fileData: true is set in DeepSeek image part provider options, the SDK expects the image content to be inline data, not a URL — fileData mode uploads inline bytes. Supplying a URL part with fileData: true throws InvalidPromptError.

Source

Thrown at packages/deepseek/src/chat/convert-to-deepseek-chat-messages.ts:193

                  functionality: `DeepSeek image media type ${resolvedMediaType}`,
                  message:
                    'DeepSeek supports JPEG, PNG, GIF, and WebP image inputs.',
                });
              }

              if (part.data.type === 'url') {
                const url = part.data.url.toString();

                if (url.length > 8192) {
                  throw new InvalidPromptError({
                    prompt,
                    message:
                      'DeepSeek image URLs must not exceed 8192 characters.',
                  });
                }

                if (filePartOptions?.fileData === true) {
                  throw new InvalidPromptError({
                    prompt,
                    message:
                      'DeepSeek `fileData` image parts require inline data, not a URL.',
                  });
                }

                userContent.push({
                  type: 'image_url',
                  image_url: {
                    url,
                    ...(filePartOptions?.imageDetail != null && {
                      detail: filePartOptions.imageDetail,
                    }),
                  },
                });
              } else {
                const dataUrl = `data:${
                  resolvedMediaType === 'image/jpg'

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Remove fileData: true from URL-based image parts
  2. Or switch the part to inline data (Uint8Array/binary) and keep fileData: true

Example fix

// before
{ type: 'image', image: new URL('https://.../img.png'), providerOptions: { deepseek: { fileData: true } } }
// after
{ type: 'image', image: new URL('https://.../img.png') }
Defensive patterns

Strategy: validation

Validate before calling

function assertFileDataNotUrl(part) {
  if (part.providerOptions?.deepseek?.fileData === true && (part.image instanceof URL || typeof part.image === 'string' && part.image.startsWith('http'))) {
    throw new Error('fileData: true requires inline image data, not a URL');
  }
}

Type guard

function isUrlImagePart(p): p is { image: URL | string } {
  return typeof p.image === 'string' || p.image instanceof URL;
}

Try / catch

try { ... } catch (e) { if (InvalidPromptError.isInstance(e) && /fileData/.test(e.message)) { /* drop fileData or inline the data */ } throw e; }

Prevention

When it happens

Trigger: Setting experimental_providerOptions: { deepseek: { fileData: true } } on an image part whose data.type is 'url' — e.g. { type: 'image', image: new URL(...), providerOptions: { deepseek: { fileData: true } } }.

Common situations: Reusing the same message-building code for both URL-based and data-based images and globally enabling fileData; misunderstanding fileData as a way to pass URL references to DeepSeek files API.

Related errors


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