vercel/ai · error · InvalidPromptError

DeepSeek assistant prefix completion requires `prefix: true`

Error message

DeepSeek assistant prefix completion requires `prefix: true` on an assistant message.

What it means

DeepSeek's assistant-prefix (FIM-style) completion is only valid on assistant messages. The SDK throws InvalidPromptError when provider options set prefix: true on a message whose role is not 'assistant' (the check reads deepseekMessageOptions?.prefix === true && role !== 'assistant').

Source

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

      lastUserMessageIndex = i;
      break;
    }
  }

  let index = -1;
  for (const { role, content, providerOptions } of prompt) {
    index++;

    // The assistant schema extends the common message schema, so one parse
    // validates names for every role and the assistant-only prefix option.
    const deepseekMessageOptions = await parseProviderOptions({
      provider: providerOptionsName,
      providerOptions,
      schema: deepseekAssistantMessageProviderOptions,
    });

    if (deepseekMessageOptions?.prefix === true && role !== 'assistant') {
      throw new InvalidPromptError({
        prompt,
        message:
          'DeepSeek assistant prefix completion requires `prefix: true` on an assistant message.',
      });
    }

    switch (role) {
      case 'system': {
        messages.push({
          role: 'system',
          content,
          ...(deepseekMessageOptions?.name != null && {
            name: deepseekMessageOptions.name,
          }),
        });
        break;
      }

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Move prefix: true to the final assistant message's provider options
  2. Remove prefix: true from any user/system/tool messages
  3. Check message.role === 'assistant' before attaching the prefix option

Example fix

// before
{ role: 'user', content: 'Say hi.', providerOptions: { deepseek: { prefix: true } } }
// after
{ role: 'assistant', content: 'Hi!', providerOptions: { deepseek: { prefix: true } } }
Defensive patterns

Strategy: validation

Validate before calling

function assertPrefixOnlyOnAssistant(messages) {
  for (const m of messages) {
    if (m.providerOptions?.deepseek?.prefix === true && m.role !== 'assistant') {
      throw new Error('prefix: true is only allowed on assistant messages');
    }
  }
}

Type guard

function isPrefixedAssistant(m): m is typeof m & { role: 'assistant' } {
  return m.role === 'assistant' && m.providerOptions?.deepseek?.prefix === true;
}

Try / catch

try { await generateText({ model: deepseek(model), messages }); } catch (e) { if (InvalidPromptError.isInstance(e)) { /* fix message options */ } throw e; }

Prevention

When it happens

Trigger: Passing prefix: true via deepseek provider options on a user, system, or tool message, e.g. experimental_providerOptions: { deepseek: { prefix: true } } on a non-assistant message in a prompt array.

Common situations: Porting OpenAI-style prefix code where the flag was applied generically to all messages; generating options in a loop without checking role; misunderstanding that prefix is the message role rather than an option.

Related errors


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