Todos los artículos

llama.cpp «System message must be at the beginning»: 3 soluciones probadas (2026)

«System message must be at the beginning» significa que la plantilla de chat del modelo rechazó la petición: el mensaje de sistema no era el primero, o había dos. Tres soluciones probadas: un solo mensaje inicial, --chat-template chatml o editar una copia de la plantilla.

Error de mensaje de sistema en llama.cpp: burbujas de chat de arcilla en orden incorrecto junto a un servidor de arcilla con triángulo rojo
También disponible en中文English

Respuesta corta: el error no viene del motor de llama.cpp. Viene de la plantilla de chat que va dentro de tu archivo de modelo. Esa plantilla dice que un mensaje de sistema solo puede ser el primer mensaje, y tu cliente envió uno en otro lugar, o envió dos. La solución limpia está en el cliente: junta todo en un único mensaje de sistema en la posición 0. Si no puedes cambiar el cliente, arranca el servidor con una plantilla más permisiva, por ejemplo --chat-template chatml. Reproduje el error en la compilación 11963 de llama.cpp y probé las tres soluciones de abajo.

Qué significa «System message must be at the beginning»

El texto completo del error de llama-server se ve así (recorté la parte central):

{"error":{"code":400,"message":"Unable to generate parser for this template. Automatic parser generation failed: ... Error: Jinja Exception: System message must be at the beginning.","type":"invalid_request_error"}}

Las versiones nuevas de llama-server leen la plantilla Jinja guardada en el archivo GGUF y la ejecutan en cada petición (la opción --jinja viene activada por defecto, según el README del servidor de llama.cpp). Algunas plantillas incluyen una comprobación. El chat_template.jinja de Qwen/Qwen3.5-35B-A3B en Hugging Face, por ejemplo, tiene la línea raise_exception('System message must be at the beginning.'). Cuando salta, llama.cpp devuelve HTTP 400 con el mensaje de arriba.

Tres cosas son ciertas a la vez: los pesos del modelo están bien, tu memoria está bien, y lo que la plantilla rechaza es la petición.

Cómo lo reproduje (probado)

No ejecuté Qwen3.5. Para que la prueba fuera pequeña usé el modelo de prueba de 1,19 MB stories260K.gguf del repositorio ggml-org en Hugging Face y le di al servidor una plantilla con la misma comprobación (si el mensaje de sistema no es el primero → raise_exception). El servidor fue llama.cpp compilación 11963 en Linux, solo CPU:

llama-server -m stories260K.gguf --jinja --chat-template-file tpl.jinja --port 18091 -c 512

Luego envié cuatro peticiones a /v1/chat/completions:

Mensajes enviadosResultado
user, luego systemHTTP 400, «System message must be at the beginning.»
system, system, userHTTP 400, el mismo error (el segundo system no es el primero)
system, user, assistant, system, userHTTP 400, el mismo error
un solo system combinado, luego userOK, el modelo respondió

La segunda fila es la que más sorprende. No hace falta un mensaje tardío: dos mensajes de sistema seguidos bastan.

También puedes ver qué plantilla cargó el servidor: curl localhost:8080/props devuelve un campo chat_template con el texto de la plantilla (comprobé que ese campo existe en la compilación 11963).

Solución 1: un solo mensaje de sistema, el primero (en el cliente)

Es la solución limpia. Junta todas las instrucciones en un mensaje y ponlo primero:

{"messages":[
 {"role":"system","content":"Regla A.\n\nRegla B."},
 {"role":"user","content":"hi"}
]}

En mi prueba esta petición pasó. Si una herramienta o extensión añade un «recordatorio de sistema» a mitad de la conversación, busca un ajuste que combine los prompts de sistema o desactiva esa función. Qué ajuste existe depende del cliente, así que revisa su propia documentación.

Solución 2: arrancar el servidor con una plantilla que no comprueba

Si no puedes cambiar el cliente, sustituye la plantilla del modelo. El README de llama.cpp lista plantillas integradas y chatml es una de ellas. Su sección de llamadas a herramientas también nombra --chat-template chatml como opción de último recurso que puede funcionar, así que es un recurso conocido:

llama-server -m model.gguf --jinja --chat-template chatml

En mi prueba, la misma petición mala (user y luego system) recibió una respuesta normal con la plantilla integrada chatml. Dos advertencias:

  • La plantilla integrada puede no coincidir con el formato con el que se entrenó tu modelo. Las respuestas pueden empeorar un poco. Prueba tus propios prompts.
  • Si usas llamadas a herramientas, el README dice que puede hacer falta un --chat-template-file compatible con herramientas. No cambies de plantilla a ciegas.

Solución 3: editar una copia de la plantilla del propio modelo

Descarga el chat_template.jinja de la página del modelo en Hugging Face, borra o relaja la rama raise_exception('System message must be at the beginning.') y cárgalo:

llama-server -m model.gguf --jinja --chat-template-file my-template.jinja

Así conservas el formato del modelo, pero un mensaje en una posición rara puede acabar renderizado en un sitio que el modelo no vio al entrenarse. Úsalo como apaño y guarda el archivo original para comparar.

Lo que no es

Más mensajes de llama.cpp y Ollama están reunidos en la lista de errores de Ollama y llama.cpp. Si aún estás eligiendo modelo, mira los mejores LLM locales.

Preguntas frecuentes

¿Este error significa que mi archivo de modelo está roto?

No. El archivo cargó y el servidor arrancó. Solo se rechazó la petición, por la comprobación de la plantilla.

¿Por qué pasa con algunos modelos y con otros no?

Solo algunas plantillas incluyen esta comprobación. La de Qwen3.5 sí; no encontré la frase en la configuración del tokenizador de Qwen3-8B que revisé, y no revisé otros modelos.

¿Arregla esto --no-jinja?

No lo probé. El README dice que --jinja está activado por defecto y que las llamadas a herramientas lo necesitan, así que desactivarlo no es buena primera opción. Primero combina los mensajes de sistema.

¿Qué diferencia hay entre --chat-template y --chat-template-file?

La primera recibe el nombre o el texto de una plantilla; la segunda, la ruta de un archivo. Ambas reemplazan la plantilla guardada en el modelo.

Fuentes y notas de prueba

  • README del servidor de llama.cpp (opciones, plantillas integradas, nota sobre herramientas): github.com/ggml-org/llama.cpp, tools/server/README.md.
  • chat_template.jinja de Qwen3.5-35B-A3B en Hugging Face (contiene la cadena exacta).
  • Probado por mí: llama.cpp compilación 11963, Linux solo CPU, stories260K.gguf con una plantilla con la comprobación escrita por mí. No probado: pesos reales de Qwen3.5, llamadas a herramientas, --no-jinja.

Deja una idea

Tu dirección de correo no se publicará.