16. Results, statistics and errors
16.1 The response
A query returns its rows, then execution statistics:
{"documents":[…],
"statistics":{"committed":false,"compact":false,"deleted":0,"filtered":1,"inserted":0,
"replaced":0,"returned":3,"scanned":4,
"strategies":["collection_scan"],"streamed":true,
"timings_us":{"parse":29,"plan":116,"execute":436,"materialize_response":55}}}
| Field | Meaning |
|---|---|
scanned, filtered, returned | Rows read, rejected by predicates, emitted |
inserted, replaced, deleted, committed | Write counters, and whether a transaction committed |
strategies | Physical strategies used: collection_scan, primary_key_lookup, direct_count, in_memory_sort, streaming_count… |
streamed | Whether rows were sent as they were produced |
timings_us | Per-phase timings in microseconds |
Numbers on the wire. Integers above 2³² are sent as floats so that JavaScript clients never lose precision silently; integers beyond 2⁵³ are refused. A client sending such an integer may also send it as a float: og-core takes a whole float where it expects an integer count (pool and policy limits, for example).
16.2 Error layers
Every message carries a byte span or a stage location.
| Layer | When | Examples |
|---|---|---|
| Lexer | An unknown character, a bad string or number | lex error: unexpected character '$' at 27..28 |
| Parser | The pipeline structure | parse error: expected stage name, found operator at 11..12, unexpected 'end' outside a sub-pipeline, sub-pipeline opened by stage at … is missing '| end'; written with ; and lines: `;` at line 1 in a query separated by `|`, empty stage before `;` at line 1, `lookup` at line 2 opens a block that no `end` closes; line 3 starts a new stage `into`: …, `end` at line 3 closes no block |
| Preparation | Parameters, let, views | variable $min is not bound, view x is not defined, a query in let returns at most 1000 rows |
| Planner | Stage arguments, expressions, placement | unknown stage "aggregate", unknown function `nope` , function `abs` expects 1 argument(s), got 2, limit operator is duplicated, follows a terminal operator |
| Execution | Data-dependent | field path "nickname" is missing, operation "==" is incompatible with values …, division by zero; use div(a, b, fallback) …, single expected exactly 1 row(s), found 0 |
| Memory | No bounded executor, or the budget is exceeded | materialized fallback is forbidden by the memory contract, a window partition exceeds the governed query working set |
Request-level codes returned by ogd: query.invalid (preparation or planning), query.execution_failed,
query.read_only_violation, view.invalid, view.forbidden.
16.3 Reading an execution error
query execution failed: storage execution error: storage backend error: expression evaluation failed: field path "date" is missing
Read it from the right: the evaluator could not read date on a row. Find the stage reading date, then either
filter the rows that lack it first (where date? != null) or read it optionally (date?, coalesce(date?, …)).
| Message | Usual cause | Fix |
|---|---|---|
field path "x" is missing | A row lacks x | x?, exists(x), an earlier where x? != null |
incompatible with values | Comparing a number and a string | to_float, to_string, or fix the import types |
`upper` expects a string, found Null | A function given null | coalesce(x?, "") |
division by zero | / by 0 | div(a, b, fallback) |
follows a terminal operator | A stage after count or a write | Use group with a constant key instead of count |
materialized fallback is forbidden | Two blocking stages with nothing to bound them, in an unsupported order | Reorder, add limit, or materialize a view |
Write errors roll back the whole transaction.