Quase todo INVALID_ARGUMENT desse tipo vem do envio de mensagens no formato da OpenAI ao endpoint nativo generateContent do Google. Ele usa nomes de roles diferentes, tem um local separado para as instruções do sistema e não tolera um turno vazio.
O erro
{"error":{"code":400,
"message":"Please use a valid role: user, model.",
"status":"INVALID_ARGUMENT"}}
{"error":{"code":400,
"message":"* GenerateContentRequest.contents: contents is not specified\n",
"status":"INVALID_ARGUMENT"}}Causas e soluções em resumo
| Causa | Solução |
|---|---|
| Mensagens no formato da OpenAI enviadas ao endpoint nativo | assistant → model, e system vai para systemInstruction. Nada mais é permitido. |
| Array contents vazio | Todas as mensagens foram filtradas — geralmente um turno de ferramenta com content: null. |
| Um turno com um array parts vazio | Substitua por uma parte de texto vazia em vez de emitir um turno sem parts. |
| Dados de imagem inline sem mimeType | inline_data precisa de mime_type e de dados base64. |
Descubra em qual API você realmente está
O mesmo nome de SDK pode ocultar dois schemas incompatíveis: o generateContent nativo do Google, que recebe contents com roles user e model, e um /v1/chat/completions compatível com a OpenAI, que recebe messages com system, user e assistant. Todo erro desta família é um payload escrito para uma API e enviado à outra.
Mapeie as roles se estiver usando a API nativa
As mensagens system e developer são reunidas em um campo systemInstruction separado. assistant vira model. user permanece user. Qualquer outra role não tem equivalente e precisa ser removida ou combinada antes do envio.
def to_gemini(messages):
system, contents = [], []
for m in messages:
if m["role"] in ("system", "developer"):
system.append(m["content"])
continue
if m["role"] not in ("user", "assistant"):
continue # no Gemini equivalent
parts = [{"text": m["content"] or ""}] # never emit empty parts
contents.append({
"role": "model" if m["role"] == "assistant" else "user",
"parts": parts,
})
req = {"contents": contents}
if system:
req["systemInstruction"] = {"parts": [{"text": "\n\n".join(system)}]}
return reqNunca emita um turno sem parts
Uma mensagem cujo content era null ou foi filtrado até ficar vazio produz um turno sem parts, que é rejeitado. Substituir por uma parte de texto vazia mantém o turno válido e preserva a alternância esperada pelo modelo.
Valide antes de enviar
Verifique que contents não está vazio, que toda role é user ou model e que todo turno tem pelo menos uma part. Três linhas no ponto de chamada, em vez de um 400 vindo da rede.
Se você estiver chamando pela Kunavo
Chamar o Gemini pela rota /v1/chat/completions compatível com a OpenAI da Kunavo significa que você nunca precisa construir manualmente o array contents do Google: envia mensagens no formato da OpenAI, e o gateway faz o mapeamento — mensagens system e developer reunidas em systemInstruction, assistant reescrita como model, roles sem equivalente removidas e uma parte de texto vazia substituída em vez de emitir um turno sem parts. Portanto, essa classe inteira de INVALID_ARGUMENT não surge do formato das mensagens. O que ele não pode evitar é um argumento realmente inválido — um response_format incompatível ou uma imagem inline malformada — que continuará sendo rejeitado por seus próprios méritos. As tarifas por token da linha Gemini estão em nosso guia de preços do Gemini.
Perguntas frequentes
Quais são as roles válidas do Gemini?
Na API nativa, exatamente duas: user e model. Não existe a role system — as instruções do sistema vão para o campo separado systemInstruction.
Posso enviar uma mensagem system?
Não como um turno. Mova-a para systemInstruction ou use um endpoint compatível com a OpenAI que faça isso por você.
Por que o payload idêntico funciona na OpenAI?
Porque o schema da OpenAI define as roles system e assistant, enquanto o schema nativo do Gemini não. O payload é válido — para a outra API.
Guias relacionados
- API do Gemini 429 RESOURCE_EXHAUSTED — cota vs. limite de taxa, corrigido corretamente
- A chave da API do Gemini não funciona — API_KEY_INVALID e suas cinco causas
Mais detalhes sobre o significado dos erros estão em referência de erros; obter uma chave leva um minuto por meio de cadastro e da guia de autenticação.