Limits
Every structural limit the reference parser enforces, with the value and what happens when you cross it.
The reference parser allocates each query from a fixed-size arena, which is how it parses without touching the heap. Those fixed sizes are the language's practical limits, and every one of them is a query someone will eventually write.
None of these are configurable.
Hard limits
Crossing any of these rejects the query.
| Limit | Value | Error |
|---|---|---|
| AST nodes per query | 64 | arena overflow: too many AST nodes (max 64) |
| Anchors per query | 32 | arena overflow: too many anchors (max 32) |
| String bytes per query | 4096 | arena overflow: string buffer exhausted (max 4096 bytes) |
| Elements in one vector literal | 4096 | vector too large (max 4096 elements) |
| Anchors in one list | 8 | too many anchors in list (max 8) |
| Namespace includes | 8 | too many namespace includes (max 8) |
| Namespace excludes | 8 | too many namespace excludes (max 8) |
| Expression nesting depth | 128 | expression nesting too deep (max 128) |
Children per AND / OR node |
16 | structural — see below |
"String bytes per query" is the total across every anchor and namespace name in the query, not per string. A query with twenty long phrase anchors can exhaust it even though no single anchor is close to the cap.
"Anchors in one list" applies separately to toward, attract and repel.
One soft limit
| Limit | Value | Behaviour |
|---|---|---|
| Vector floats per query | 8192 | Falls back to a heap allocation |
This one does not reject the query. When the vector arena is exhausted the parser allocates from the heap and carries on, so the only consequence is that the parse is no longer allocation-free.
It matters if you are relying on the zero-allocation property on a hot path, and not at all otherwise. Two 4096-element vector anchors reach it exactly.
The 16-child limit
A boolean node holds at most 16 children. There is no dedicated error message
for exceeding it, because the parser builds AND and OR as nested binary
nodes rather than one flat list — a 20-clause AND becomes a deeper tree, not
an over-full node, and it is the 64-node or 128-depth limit you meet first.
The 16 matters when constructing JSON by hand: a single {"and": [...]} array
with more than 16 entries has no valid parse.
Working within them
64 nodes is a lot of query. If you are approaching it, the usual cause is a
generated OR over a list that grew — one clause per item in a catalogue, say.
That shape is better served by a broader
DIRECTION or a
CONTRAST that names the shared quality, which is
also more likely to match items nobody has added yet.