Repository navigation
json-schema-to-grammar : convert empty anyOf / oneOf / type unions instead of emitting an empty rule - #333
Open
professorpalmer wants to merge 1 commit into
Conversation
…stead of emitting an empty rule
A schema with an empty union ("anyOf": [], "oneOf": [] or "type": []) produced a rule with no
alternatives ("root ::=" for a root schema). The grammar parser rejects it, so the request fails
with "failed to parse grammar". Schema generators used by agent frameworks emit such unions, and
the failure ends the agent's turn. The keyword constrains nothing, so drop it and convert the rest
of the schema, in the C++ and the Python converter. Adds test cases for both converters.
Reported-by: Milor123 (professorpalmer/bonsai-ada-surgery#3)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
A JSON schema with an empty union (
"anyOf": [],"oneOf": []or"type": []) makesjson-schema-to-grammaremit arule with no alternatives. For a root schema that is
root ::=followed by thespacerule; the grammar parser rejectsit and the request fails with
Failed to initialize samplers: failed to parse grammar. Reproduces onprismwith anymodel:
Agent frameworks emit these unions from generated schemas (reported against a Bonsai 2 27B serve by Milor123 running
Hermes Agent: professorpalmer/bonsai-ada-surgery#3), and the failure ends the agent's turn. The same happens when the
empty union sits inside a tool parameter's schema.
This PR drops an empty union keyword and converts the rest of the schema, in the C++ converter and in
examples/json_schema_to_grammar.py(kept in sync, astest-json-schema-to-grammarruns both). An emptyanyOfonits own therefore converts like
{};{"type": [], "properties": {...}}converts like the object withouttype.Additional information
ggml-org/llama.cpphandles this since its schema rewrite (common : implement common_schema internal representation for JSON schemas ggml-org/llama.cpp#28736, merged 2026-09-12),which
prismhas not synced yet: there the empty union is rejected up front with a clear "must not be empty" schemaerror. So the choice for this fork is between this conversion (the request succeeds) and backporting upstream's
rejection (the request still fails, with a readable message). I went with conversion because the reported failure is
an agent loop that cannot recover from a 400, and the keyword constrains nothing; happy to switch to a minimal
"reject with a clear error" version instead if you prefer to match upstream until the next sync.
tests/test-json-schema-to-grammar.cpp(emptyanyOf, emptyoneOf, emptytypewithproperties, empty unions inside properties). The full test passes for C++, Python and the expectation-validity pass;
without the C++ change the new
empty anyOfcase fails. Run on our fork, whose three touched files arebyte-identical to
prismat 6bfcd79.unchanged on unrelated prompts.
Requirements
the change and the test cases and ran the tests; I reviewed the change and the test output and can explain both.