Presque toutes les erreurs INVALID_ARGUMENT de cette forme proviennent de l’envoi de messages au format OpenAI vers le point de terminaison natif generateContent de Google. Les noms de rôles sont différents, les instructions système disposent d’un emplacement distinct et un tour vide n’est pas toléré.
L’erreur
{"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"}}Causes et solutions en bref
| Cause | Solution |
|---|---|
| Messages au format OpenAI envoyés au point de terminaison natif | assistant → model, et system devient systemInstruction. Rien d’autre n’est autorisé. |
| Tableau contents vide | Tous les messages ont été filtrés — souvent un tour d’outil avec content: null. |
| Un tour avec un tableau parts vide | Remplacez-le par une partie de texte vide au lieu d’émettre un tour sans partie. |
| Données d’image intégrées sans mimeType | inline_data nécessite à la fois mime_type et les données base64. |
Déterminez d’abord quelle API vous utilisez réellement
Le même nom de SDK masque deux schémas incompatibles : le generateContent natif de Google, qui accepte contents avec les rôles user et model, et un /v1/chat/completions compatible OpenAI, qui accepte messages avec system, user et assistant. Toutes les erreurs de cette famille proviennent d’un contenu préparé pour une API puis envoyé à l’autre.
Convertissez les rôles si vous utilisez l’API native
Les messages system et developer sont regroupés dans un champ systemInstruction distinct. assistant devient model. user reste user. Tout autre rôle n’a pas d’équivalent et doit être supprimé ou fusionné avant l’envoi.
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 reqN’émettez jamais un tour sans partie
Un message dont le contenu est null ou qui a été entièrement filtré produit un tour sans partie, qui est rejeté. Remplacer celui-ci par une partie de texte vide maintient la validité du tour et préserve l’alternance attendue par le modèle.
Validez avant l’envoi
Vérifiez que contents n’est pas vide, que chaque rôle est user ou model et que chaque tour contient au moins une partie. Trois lignes au point d’appel, plutôt qu’une erreur 400 renvoyée par le réseau.
Si vous appelez via Kunavo
Appeler Gemini via le /v1/chat/completions compatible OpenAI de Kunavo vous évite de construire vous-même le tableau contents de Google : vous envoyez des messages au format OpenAI et la passerelle effectue la conversion — les messages system et developer sont regroupés dans systemInstruction, assistant est converti en model, les rôles sans équivalent sont supprimés et une partie de texte vide est substituée au lieu d’émettre un tour sans partie. Cette catégorie entière d’erreurs INVALID_ARGUMENT ne provient donc pas de la structure des messages. En revanche, elle ne peut pas vous protéger contre un argument réellement invalide — par exemple un response_format non pris en charge ou une image intégrée mal formée — qui sera toujours rejeté pour ce motif. Les tarifs par token pour la gamme Gemini sont indiqués dans notre guide des tarifs Gemini.
Questions fréquentes
Quels sont les rôles valides de Gemini ?
Sur l’API native, exactement deux : user et model. Il n’existe pas de rôle system ; les instructions système vont dans le champ systemInstruction distinct.
Puis-je envoyer un message système ?
Pas comme un tour. Déplacez-le dans systemInstruction ou utilisez un point de terminaison compatible OpenAI qui s’en charge pour vous.
Pourquoi le même contenu fonctionne-t-il avec OpenAI ?
Parce que le schéma d’OpenAI définit les rôles system et assistant, contrairement au schéma natif de Gemini. Le contenu est valide — pour l’autre API.
Guides associés
- API Gemini 429 RESOURCE_EXHAUSTED — quota ou limite de débit, correction appropriée
- Clé API Gemini inactive — API_KEY_INVALID et ses cinq causes
La sémantique détaillée des erreurs est disponible dans référence des erreurs ; obtenir une clé prend une minute via inscription et la guide d’authentification.