Name and Version
$./llama-server --version
version: 9595 (79697f23a)
built with AppleClang 17.0.0.17000013 for Darwin arm64
Branch: prism (this fork), commit 79697f23a2c8f3aa2ccb2fd7406095a8dbfbb454.
Operating systems
Mac
Which llama.cpp modules do you know to be affected?
llama-server (peg-native tool-call grammar generation / src/llama-grammar.cpp)
Command line
./build/bin/llama-server -m Ternary-Bonsai-27B-Q2_0.gguf -c 65536 --port 8080 -ngl 99 --temp 0.7 --top-p 0.95 --top-k 20 --jinja
Problem description & steps to reproduce
When serving Ternary-Bonsai-27B-Q2_0.gguf with a moderately large tool set (~26 OpenAI-style tool definitions, sent via /v1/chat/completions tools[], e.g. from an agent client like OpenClaw) and a large context window (-c 65536), grammar compilation for the peg-native tool-call format fails on every request with:
parse: error parsing grammar: number of repetitions exceeds sane defaults, please reduce the number of repetitions
This is MAX_REPETITION_THRESHOLD (src/llama-grammar.cpp:13, currently 2000) being tripped by the check at src/llama-grammar.cpp:652-653.
Root cause: tool parameters with no maxLength (e.g. a plain {"type": "string"} arg — very common, e.g. write's path/content params) get an unbounded until-suffix-style GBNF matcher during PEG→GBNF conversion (common_peg_until_parser, see common/chat-auto-parser-generator.cpp and common/peg-parser.cpp). Since the internal grammar sampler needs a concrete finite bound rather than a true *, this gets converted to a {min,max} repetition where max is derived from the server's context size (confirmed empirically: with -c 65536, the failing check reported min_times=1 max_times=65536 — the value matches the context size exactly, not any schema-declared bound). With 26 tools active, many individual string params hit this same context-sized bound, and each one independently trips the 2000 threshold via the direct (non-multiplicative) check at line 652.
Silent fallback is the dangerous part: when grammar compilation throws, the server does not surface this as a client-facing error — it logs E failed to parse grammar and apparently proceeds without a compiled constraint grammar for that turn. This lets the model free-generate its tool call instead of being constrained to valid peg-native syntax, which then fails a second, unrelated parse step downstream (Failed to parse input at pos N: <tool_call>...) once the (unconstrained, occasionally malformed) completion comes back. So the user-visible symptom is a confusing "failed to parse input" 500 on the response side, when the real root cause is a silent grammar-compile failure on the request side, several steps earlier.
Repro:
- Start
llama-server with -c 65536 and Ternary-Bonsai-27B-Q2_0.gguf.
- Send a
/v1/chat/completions request with tools[] containing ~20+ tool definitions where several have unbounded string parameters (no maxLength).
- Observe
E failed to parse grammar / number of repetitions exceeds sane defaults in the server log, immediately followed by processing proceeding anyway (no compiled grammar constraining output).
- The model's completion, if it doesn't happen to match
peg-native syntax exactly, then fails the response parser with Failed to parse input at pos N.
Confirmed fix: raising MAX_REPETITION_THRESHOLD from 2000 to 100000 (comfortably above 65536) in src/llama-grammar.cpp and rebuilding resolves it — verified via a full write→read→cron-add→cron-list→cron-remove multi-tool-call test with all 26 tools active, temp 0.7 (per the model's recommended sampling settings), which now completes cleanly with real tool execution and no parse errors.
Suggested fix
A few options, roughly in order of preference:
- Raise
MAX_REPETITION_THRESHOLD (or make it configurable via CLI flag / env var) — simplest, but a blunt instrument since it's a general sanity cap, not specific to this code path.
- Cap the "no
maxLength declared" fallback bound to something more reasonable than the full context size (e.g. a fixed constant like 4096 or 8192 characters) when converting common_peg_until_parser to GBNF, rather than deriving it from n_ctx. A tool argument string very rarely needs to be context-length-sized, and this would scale independently of -c.
- At minimum, surface grammar-compile failures as a client-facing error (e.g. a 500 with a clear message) instead of silently falling back to unconstrained generation — the current behavior turns a clear, actionable error ("grammar too complex, reduce tool count or param bounds") into a confusing downstream parse failure that looks unrelated to its actual cause.
Relevant log output
Logs
I srv params_from_: Chat format: peg-native
I slot get_availabl: id 3 | task -1 | selected slot by LCP similarity, sim_best = 0.997 (> 0.100 thold), f_keep = 0.995
parse: error parsing grammar: number of repetitions exceeds sane defaults, please reduce the number of repetitions
E failed to parse grammar
...
[response, several seconds later]
Failed to parse input at pos 237: <tool_call>
<function=write>
<parameter=content>
full tool test
</parameter>
<parameter=path>
/Users/livestream/.openclaw/workspace/fulltooltest.txt
</parameter>
</function>
</tool_call>
Debug instrumentation added locally (not in this repro, but confirms the mechanism) at the failing check printed:
[DEBUG-REPCHECK-B] min_times=1 max_times=65536 has_max=1 threshold=20000
(65536 was the -c value passed at startup; threshold shown was an intermediate value of 20000 while narrowing down the fix, not the default 2000.)
Name and Version
Branch:
prism(this fork), commit79697f23a2c8f3aa2ccb2fd7406095a8dbfbb454.Operating systems
Mac
Which llama.cpp modules do you know to be affected?
llama-server (peg-native tool-call grammar generation /
src/llama-grammar.cpp)Command line
Problem description & steps to reproduce
When serving Ternary-Bonsai-27B-Q2_0.gguf with a moderately large tool set (~26 OpenAI-style tool definitions, sent via
/v1/chat/completionstools[], e.g. from an agent client like OpenClaw) and a large context window (-c 65536), grammar compilation for thepeg-nativetool-call format fails on every request with:This is
MAX_REPETITION_THRESHOLD(src/llama-grammar.cpp:13, currently2000) being tripped by the check atsrc/llama-grammar.cpp:652-653.Root cause: tool parameters with no
maxLength(e.g. a plain{"type": "string"}arg — very common, e.g.write'spath/contentparams) get an unboundeduntil-suffix-style GBNF matcher during PEG→GBNF conversion (common_peg_until_parser, seecommon/chat-auto-parser-generator.cppandcommon/peg-parser.cpp). Since the internal grammar sampler needs a concrete finite bound rather than a true*, this gets converted to a{min,max}repetition wheremaxis derived from the server's context size (confirmed empirically: with-c 65536, the failing check reportedmin_times=1 max_times=65536— the value matches the context size exactly, not any schema-declared bound). With 26 tools active, many individual string params hit this same context-sized bound, and each one independently trips the2000threshold via the direct (non-multiplicative) check at line 652.Silent fallback is the dangerous part: when grammar compilation throws, the server does not surface this as a client-facing error — it logs
E failed to parse grammarand apparently proceeds without a compiled constraint grammar for that turn. This lets the model free-generate its tool call instead of being constrained to validpeg-nativesyntax, which then fails a second, unrelated parse step downstream (Failed to parse input at pos N: <tool_call>...) once the (unconstrained, occasionally malformed) completion comes back. So the user-visible symptom is a confusing "failed to parse input" 500 on the response side, when the real root cause is a silent grammar-compile failure on the request side, several steps earlier.Repro:
llama-serverwith-c 65536and Ternary-Bonsai-27B-Q2_0.gguf./v1/chat/completionsrequest withtools[]containing ~20+ tool definitions where several have unbounded string parameters (nomaxLength).E failed to parse grammar/number of repetitions exceeds sane defaultsin the server log, immediately followed by processing proceeding anyway (no compiled grammar constraining output).peg-nativesyntax exactly, then fails the response parser withFailed to parse input at pos N.Confirmed fix: raising
MAX_REPETITION_THRESHOLDfrom2000to100000(comfortably above65536) insrc/llama-grammar.cppand rebuilding resolves it — verified via a full write→read→cron-add→cron-list→cron-remove multi-tool-call test with all 26 tools active, temp 0.7 (per the model's recommended sampling settings), which now completes cleanly with real tool execution and no parse errors.Suggested fix
A few options, roughly in order of preference:
MAX_REPETITION_THRESHOLD(or make it configurable via CLI flag / env var) — simplest, but a blunt instrument since it's a general sanity cap, not specific to this code path.maxLengthdeclared" fallback bound to something more reasonable than the full context size (e.g. a fixed constant like 4096 or 8192 characters) when convertingcommon_peg_until_parserto GBNF, rather than deriving it fromn_ctx. A tool argument string very rarely needs to be context-length-sized, and this would scale independently of-c.Relevant log output
Logs
Debug instrumentation added locally (not in this repro, but confirms the mechanism) at the failing check printed:
(
65536was the-cvalue passed at startup; threshold shown was an intermediate value of20000while narrowing down the fix, not the default2000.)