quickwit-oss/quickwit · error
Failed to serialize QueryAst
Error message
Failed to serialize QueryAst
What it means
When translating an Elasticsearch search request into a gRPC SearchRequest, the parsed QueryAst is serialized to a JSON string stored in the query_ast field. Serialization of QueryAst is an invariant, so serde_json::to_string failing triggers this expect panic.
Source
Thrown at quickwit/quickwit-serve/src/elasticsearch_api/rest_handler.rs:572
})
.take_while_inclusive(|sort_field| !is_doc_field(sort_field))
.collect();
if sort_fields.len() >= 3 {
return Err(ElasticsearchError::from(SearchError::InvalidArgument(
format!("only up to two sort fields supported at the moment. got {sort_fields:?}"),
)));
}
let scroll_duration: Option<Duration> = search_params.parse_scroll_ttl()?;
let scroll_ttl_secs: Option<u32> = scroll_duration.map(|duration| duration.as_secs() as u32);
let has_doc_id_field = sort_fields.iter().any(is_doc_field);
let search_after = partial_hit_from_search_after_param(search_body.search_after, &sort_fields)?;
Ok((
quickwit_proto::search::SearchRequest {
index_id_patterns,
query_ast: serde_json::to_string(&query_ast).expect("Failed to serialize QueryAst"),
max_hits,
start_offset,
aggregation_request,
sort_fields,
start_timestamp: None,
end_timestamp: None,
snippet_fields: Vec::new(),
scroll_ttl_secs,
search_after,
count_hits,
ignore_missing_indexes,
skip_aggregation_finalization: false,
..Default::default()
},
has_doc_id_field,
))
}
View on GitHub (pinned to a39730c5cd)
Solutions
- Verify the incoming ES query body parses to a standard QueryAst (test with a minimal query)
- Align quickwit-query versions across the build
- If you extended QueryAst, implement/derive Serialize correctly and round-trip test
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate the ES query body is standard and JSON-serializable: serde_json::to_string(&parsed_query_ast).map_err(|e| ElasticsearchError::from(e))?;
Try / catch
// Wrap the ES search call:
let resp = client.search_v2(request).await?; // server-side expect; on panic, check server logs
// Client side use:
match result { Ok(v) => v, Err(e) => { log::error!("search failed: {e}"); return Err(e); } } Prevention
- Use only documented ES-compatible query DSL fields
- Add round-trip (to_string -> from_str) tests for any new QueryAst node
- Avoid unsupported custom AST payloads from third-party clients
When it happens
Trigger: convert_search_query_from_es_api (constructing quickwit_proto::search::SearchRequest) receives a QueryAst whose serde serialization fails, e.g. from a newly added AST variant missing Serialize support.
Common situations: Workspace version skew of quickwit-query; custom query AST extensions; corrupted query payloads from ES-compatible clients that deserialize but fail to re-serialize.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- QueryAst should be JSON serializable
- `doc_batch` should not be empty
- node not found in pending
- OTP logs or traces do not support VRL transforms
- Encountered unknown command: code {other}
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/822f2c82135e3dc4.
Report an issue: GitHub.