{"record":{"id":"4f10631c98ff8d25","repo":"vercel/ai","slug":"moonshot-ai-partial-mode-requires-the-partial-assi","errorCode":null,"errorMessage":"Moonshot AI Partial Mode requires the partial assistant message to be the final message.","messagePattern":"Moonshot AI Partial Mode requires the partial assistant message to be the final message\\.","errorType":"validation","errorClass":"InvalidPromptError","httpStatus":null,"severity":"error","filePath":"packages/moonshotai/src/convert-to-moonshotai-chat-messages.ts","lineNumber":295,"sourceCode":"                      functionality: `file part media type ${part.mediaType}`,\n                    });\n                  }\n                }\n              }\n            }\n          }),\n          ...(moonshotMessageOptions?.name != null && {\n            name: moonshotMessageOptions.name,\n          }),\n        });\n\n        break;\n      }\n\n      case 'assistant': {\n        if (moonshotMessageOptions?.partial === true) {\n          if (index !== prompt.length - 1) {\n            throw new InvalidPromptError({\n              prompt,\n              message:\n                'Moonshot AI Partial Mode requires the partial assistant message to be the final message.',\n            });\n          }\n\n          if (responseFormat?.type === 'json_object') {\n            throw new InvalidPromptError({\n              prompt,\n              message:\n                'Moonshot AI Partial Mode cannot be combined with JSON object response format.',\n            });\n          }\n        }\n\n        let text = '';\n        let reasoning = '';\n        const toolCalls: Array<{","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/moonshotai/src/convert-to-moonshotai-chat-messages.ts#L277-L313","documentation":"Moonshot AI 'Partial Mode' (moonshotMessageOptions.partial = true) lets you send an incomplete assistant message as a prefix for the model to continue. The Moonshot API only accepts such a partial assistant message as the LAST message of the prompt, so the converter throws InvalidPromptError if it appears earlier.","triggerScenarios":"Passing providerOptions.moonshot.partial = true on an assistant message that is not the final message in the messages array (e.g. followed by more assistant/user turns).","commonSituations":"Building a continue-generation feature but appending the partial assistant message before tool results or additional turns; iterating over histories and blindly marking the last assistant message found rather than the actual final message.","solutions":["Ensure the partial assistant message is the last element of the prompt array.","Remove additional messages that come after the partial assistant message.","Set partial: false (or omit it) if you need the message in the middle of the conversation.","Reorder so only the prefix assistant message is partial and nothing follows it."],"exampleFix":"// before\nmessages: [user('hi'), assistant('partial...', { partial: true }), user('more')]\n// after\nmessages: [user('hi'), assistant('partial...', { partial: true })]","handlingStrategy":"validation","validationCode":"const last = messages[messages.length - 1];\nif (last?.role === 'assistant' && (last.providerOptions?.moonshot as any)?.partial === true && messages.length > 1) {\n  // OK only if it IS the final message; error if any earlier message has partial\n}\nconst badIndex = messages.slice(0, -1).findIndex(m => m.role === 'assistant' && (m.providerOptions?.moonshot as any)?.partial === true);\nif (badIndex !== -1) throw new Error(`partial assistant message must be last (index ${badIndex})`);","typeGuard":"function isFinalPartialAssistant(messages: ModelMessage[]): boolean {\n  const last = messages.at(-1);\n  return !!last && last.role === 'assistant' &&\n    !messages.slice(0, -1).some(m => m.role === 'assistant' && (m.providerOptions?.moonshot as any)?.partial === true);\n}","tryCatchPattern":"import { InvalidPromptError } from '@ai-sdk/provider';\ntry {\n  await generateText({ model: moonshot(modelId), messages });\n} catch (e) {\n  if (InvalidPromptError.isInstance(e) && e.message.includes('Partial Mode')) {\n    // sanitize messages: drop trailing turns or unset partial\n  }\n  throw e;\n}","preventionTips":["Only set partial: true on the very last assistant message of the prompt.","Build a helper that appends the partial assistant message as the final element.","Never append tool results or user turns after a partial assistant message.","Add a unit test asserting the continue-generation prompt shape."],"tags":["moonshotai","invalid-prompt","partial-mode","message-order"],"backgroundTag":"invalid-message-order","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}