Casi todos los errores INVALID_ARGUMENT de este tipo se deben a enviar mensajes con formato de OpenAI al endpoint nativo generateContent de Google. Tiene nombres de roles distintos, un lugar separado para las instrucciones del sistema y no tolera un turno vacío.
El error
{"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 y soluciones de un vistazo
| Causa | Solución |
|---|---|
| Mensajes con formato de OpenAI enviados al endpoint nativo | assistant → model, y system pasa a systemInstruction. No hay nada más permitido. |
| Array de contents vacío | Todos los mensajes fueron filtrados; a menudo se trata de un turno de herramienta con content: null. |
| Un turno con un array de parts vacío | Sustituya por una parte de texto vacía en lugar de emitir un turno sin parts. |
| Datos de imagen en línea sin mimeType | inline_data necesita tanto mime_type como datos base64. |
Determine qué API está usando realmente
El mismo nombre de SDK puede ocultar dos esquemas incompatibles: generateContent nativo de Google, que acepta contents con roles user y model, y un /v1/chat/completions compatible con OpenAI, que acepta messages con system, user y assistant. Todos los errores de esta familia se deben a enviar a una API un payload escrito para la otra.
Mapee los roles si está usando la API nativa
Los mensajes system y developer se integran en un campo systemInstruction separado. assistant se convierte en model. user permanece como user. Cualquier otro rol no tiene equivalente y debe eliminarse o combinarse antes del envío.
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 reqNo emita nunca un turno sin parts
Un mensaje cuyo contenido era null o quedó vacío al filtrarse produce un turno sin parts, que se rechaza. Sustituirlo por una parte de texto vacía mantiene válido el turno y conserva la alternancia que espera el modelo.
Valide antes de enviar
Asegúrese de que contents no esté vacío, de que cada rol sea user o model y de que cada turno tenga al menos una part. Son tres líneas en el punto de llamada, frente a un 400 de la red.
Si llamas a través de Kunavo
Llamar a Gemini mediante /v1/chat/completions compatible con OpenAI de Kunavo significa que nunca debe construir manualmente el array contents de Google: envía mensajes con formato de OpenAI y el gateway realiza la conversión —los mensajes system y developer se integran en systemInstruction, assistant se reescribe como model, los roles sin equivalente se eliminan y se sustituye una parte de texto vacía en lugar de emitir un turno sin parts. Por tanto, toda esta clase de INVALID_ARGUMENT no surge por la forma del mensaje. Lo que no puede evitar es un argumento realmente inválido —un response_format no compatible o una imagen en línea mal formada—, que seguirá rechazándose por sus propios méritos. Las tarifas por token de la gama Gemini están en nuestra guía de precios de Gemini.
Preguntas frecuentes
¿Cuáles son los roles válidos de Gemini?
En la API nativa, exactamente dos: user y model. No existe el rol system; las instrucciones del sistema van en el campo separado systemInstruction.
¿Puedo enviar un mensaje del sistema?
No como turno. Muévalo a systemInstruction o use un endpoint compatible con OpenAI que lo haga por usted.
¿Por qué funciona el payload idéntico contra OpenAI?
Porque el esquema de OpenAI define los roles system y assistant, mientras que el esquema nativo de Gemini no. El payload es válido, pero para la otra API.
Guías relacionadas
- Gemini API 429 RESOURCE_EXHAUSTED: cuota frente a límite de velocidad, solución correcta
- La clave de API de Gemini no funciona: API_KEY_INVALID y sus cinco causas
Encontrarás más detalles sobre el significado de los errores en referencia de errores; obtener una clave lleva un minuto mediante registro y la guía de autenticación.