llama.cpp “System message must be at the beginning”: 3 Tested Fixes (2026)
"System message must be at the beginning" means the model's chat template refused the request: the system message was not first, or there were two. Three tested fixes: merge into one first message, start with --chat-template chatml, or edit a copy of the template.

Short answer: the error does not come from llama.cpp’s engine. It comes from the chat template that ships inside your model file. That template says “a system message is only allowed as the very first message”, and your client sent one somewhere else, or sent two. Fix it on the client side by merging everything into one system message at position 0. If you cannot change the client, start the server with a more forgiving template, for example --chat-template chatml. I reproduced the error on llama.cpp build 11963 and tested all three fixes below.
What “System message must be at the beginning” means
The full error text from llama-server looks like this (I cut the middle):
{"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"}}
Newer llama-server builds read the Jinja chat template stored in the GGUF file and run it on every request (the --jinja option is on by default, per the llama.cpp server README). Some templates contain a guard. The chat_template.jinja of Qwen/Qwen3.5-35B-A3B on Hugging Face, for example, has the line raise_exception('System message must be at the beginning.'). When the guard fires, llama.cpp returns HTTP 400 and the message above.
So three facts are true at once: the model weights are fine, your memory is fine, and the request is what the template refuses.
How I reproduced it (tested)
I did not run Qwen3.5 itself. To keep the test small, I used the 1.19 MB test model stories260K.gguf from the ggml-org repository on Hugging Face and gave the server a template file that has the same guard (system message not first → raise_exception). The server was llama.cpp build 11963 on Linux, CPU only:
llama-server -m stories260K.gguf --jinja --chat-template-file tpl.jinja --port 18091 -c 512
Then I sent four chat requests to /v1/chat/completions:
| Messages sent | Result |
|---|---|
| user, then system | HTTP 400, “System message must be at the beginning.” |
| system, system, user | HTTP 400, same error (the second system message is not first) |
| system, user, assistant, system, user | HTTP 400, same error |
| one merged system, then user | OK, the model answered |
The second row is the one that surprises people. You do not need a late message for the error: two system messages in a row are enough.
You can also see which template the server loaded. curl localhost:8080/props returns a chat_template field with the template text (I checked that this field is there in build 11963).
Fix 1: send one system message, first (client side)
This is the clean fix. Collect every instruction into a single message and put it first:
{"messages":[
{"role":"system","content":"Rule A.\n\nRule B."},
{"role":"user","content":"hi"}
]}
In my test this request passed. If a tool or extension adds a “system reminder” later in the chat, look for a setting that merges system prompts, or turn that feature off. Which setting exists depends on the client, so check its own docs.
Fix 2: start the server with a template that does not check
If you cannot change the client, replace the model’s template. The llama.cpp README lists built-in templates, and chatml is one of them. Its tool-calling section also names --chat-template chatml as a worst-case option that may work, so it is a known fallback:
llama-server -m model.gguf --jinja --chat-template chatml
In my test the same bad request (user, then system) returned a normal answer with the built-in chatml template. Two cautions:
- The built-in template may not match the format your model was trained on. Replies can get a little worse. Test your own prompts.
- If you use tool calling, the README says you may need a
--chat-template-filethat supports tools. Do not switch templates blindly there.
Fix 3: edit a copy of the model’s own template
Download the chat_template.jinja from the model’s Hugging Face page, delete or loosen the raise_exception('System message must be at the beginning.') branch, and load it:
llama-server -m model.gguf --jinja --chat-template-file my-template.jinja
This keeps the model’s own format, but a message in an odd position may then be rendered somewhere the model was not trained to see. Treat it as a workaround, and keep the original file so you can compare.
What it is not
- It is not an out-of-memory error. For memory problems read Ollama “model requires more system memory”.
- It is not the “–model or -hf is required” start-up error. That one is in llama.cpp “error: –model or -hf is required”.
- It is not a bad GGUF. A different error, “unknown model architecture”, is covered in Ollama unknown model architecture.
More llama.cpp and Ollama messages are collected in the Ollama and llama.cpp error list. If you are still choosing a model, see the best local LLMs.
FAQ
Does this error mean my model file is broken?
No. The file loaded and the server started. Only the request was refused, because of the template’s guard.
Why does it happen with some models and not others?
Only some templates contain this guard. The Qwen3.5 template does; I could not find the phrase in the Qwen3-8B tokenizer config I checked, and I did not check other models.
Is --no-jinja a fix?
I did not test it. The README says --jinja is on by default and that tool calling needs it, so turning it off is a poor first choice. Merge the system messages first.
What is the difference between --chat-template and --chat-template-file?
The first takes a template name or the template text; the second takes a file path. Both replace the template stored in the model.
Sources and test notes
- llama.cpp server README (options, built-in templates, tool-calling note): github.com/ggml-org/llama.cpp,
tools/server/README.md. - Qwen3.5-35B-A3B
chat_template.jinjaon Hugging Face (contains the exact guard string). - Tested myself: llama.cpp build 11963, Linux CPU,
stories260K.ggufwith a guard template written by me. Not tested: real Qwen3.5 weights, tool calling,--no-jinja.