Name and Version
$./llama-cli --version
version: 9350 (08bc21b)
built with GNU 13.3.0 for Linux aarch64
Operating systems
Linux
Which llama.cpp modules do you know to be affected?
libllama (core library)
Command line
Problem description & steps to reproduce
Summary
When an invalid GBNF grammar is passed to the server via the grammar field of
/completion or /chat/completions, the request is not rejected: the server
returns HTTP 200 and generates unconstrained output, with the parse error only
visible in the server logs. The documented behavior
(tools/server/README.md)
is an HTTP 400 response:
{ "error": { "code": 400, "message": "Failed to parse grammar", "type": "invalid_request_error" } }
Note that the json_schema field is unaffected: an invalid schema correctly
returns a 400, because json_schema_to_grammar() throws at request-parsing time.
Steps to reproduce
- Start
llama-server with any model.
- Send a completion request with a syntactically invalid grammar, e.g.:
curl -s http://localhost:8080/completion -d '{
"prompt": "Answer yes or no:",
"n_predict": 16,
"grammar": "root ::= this is (not valid GBNF"
}'
- Observed: HTTP 200, normal unconstrained completion;
error parsing grammar only appears in the server log.
Expected: HTTP 400 invalid_request_error, as documented.
Root cause
llama_grammar_parser::parse() catches its own exceptions and returns false
(src/llama-grammar.cpp), so llama_sampler_init_grammar() returns nullptr rather
than throwing. Before #17937, common_sampler_init() had an explicit check:
if (!grmr) {
return nullptr;
}
which allowed the server to detect the failure and send the 400. That check was
removed in commit 254098a ("common : refactor common_sampler + grammar logic
changes", #17937). Since then common_sampler_init() silently builds the sampler
with .grmr = nullptr, no exception ever reaches the server's try/catch in
launch_slot_with_task() (tools/server/server-context.cpp), and the grammar
constraint is simply dropped.
There is currently no server test covering an invalid grammar (only valid-grammar
tests exist in tools/server/tests/unit/test_chat_completion.py), which is likely
why the regression went unnoticed.
Impact
Clients relying on grammar-constrained output (strict JSON, enums, tool-call
formats…) get no signal that their constraint was dropped — malformed grammars
fail open instead of failing loudly.
bug_llama.cpp_claude_analysis.txt
First Bad Commit
254098a (#17937)
Relevant log output
Logs
Name and Version
$./llama-cli --version
version: 9350 (08bc21b)
built with GNU 13.3.0 for Linux aarch64
Operating systems
Linux
Which llama.cpp modules do you know to be affected?
libllama (core library)
Command line
Problem description & steps to reproduce
Summary
When an invalid GBNF grammar is passed to the server via the
grammarfield of/completionor/chat/completions, the request is not rejected: the serverreturns HTTP 200 and generates unconstrained output, with the parse error only
visible in the server logs. The documented behavior
(tools/server/README.md)
is an HTTP 400 response:
{ "error": { "code": 400, "message": "Failed to parse grammar", "type": "invalid_request_error" } }Note that the
json_schemafield is unaffected: an invalid schema correctlyreturns a 400, because
json_schema_to_grammar()throws at request-parsing time.Steps to reproduce
llama-serverwith any model.error parsing grammaronly appears in the server log.Expected: HTTP 400
invalid_request_error, as documented.Root cause
llama_grammar_parser::parse()catches its own exceptions and returnsfalse(
src/llama-grammar.cpp), sollama_sampler_init_grammar()returnsnullptrratherthan throwing. Before #17937,
common_sampler_init()had an explicit check:which allowed the server to detect the failure and send the 400. That check was
removed in commit 254098a ("common : refactor common_sampler + grammar logic
changes", #17937). Since then
common_sampler_init()silently builds the samplerwith
.grmr = nullptr, no exception ever reaches the server's try/catch inlaunch_slot_with_task()(tools/server/server-context.cpp), and the grammarconstraint is simply dropped.
There is currently no server test covering an invalid grammar (only valid-grammar
tests exist in
tools/server/tests/unit/test_chat_completion.py), which is likelywhy the regression went unnoticed.
Impact
Clients relying on grammar-constrained output (strict JSON, enums, tool-call
formats…) get no signal that their constraint was dropped — malformed grammars
fail open instead of failing loudly.
bug_llama.cpp_claude_analysis.txt
First Bad Commit
254098a (#17937)
Relevant log output
Logs