quickwit-oss/quickwit · error

QueryAst should be JSON serializable

Error message

QueryAst should be JSON serializable

What it means

The ListFields ES-compatible API serializes the parsed index_filter QueryAst to JSON to embed it in the gRPC ListFieldsRequest. QueryAst is guaranteed to be JSON-serializable by design, so a serialization failure indicates a bug in an AST node's Serialize impl and panics via expect.

Source

Thrown at quickwit/quickwit-serve/src/elasticsearch_api/model/field_capability.rs:224

        ElasticsearchError::new(
            StatusCode::BAD_REQUEST,
            format!("Failed to convert index_filter: {err}"),
            None,
        )
    })?;

    Ok(Some(query_ast))
}

#[allow(clippy::result_large_err)]
pub fn build_list_field_request_for_es_api(
    index_id_patterns: Vec<String>,
    search_params: FieldCapabilityQueryParams,
    search_body: FieldCapabilityRequestBody,
) -> Result<quickwit_proto::search::ListFieldsRequest, ElasticsearchError> {
    let query_ast = parse_index_filter_to_query_ast(search_body.index_filter)?;
    let query_ast_json = query_ast
        .map(|ast| serde_json::to_string(&ast).expect("QueryAst should be JSON serializable"));

    Ok(quickwit_proto::search::ListFieldsRequest {
        index_id_patterns,
        field_patterns: search_params.fields.unwrap_or_default(),
        start_timestamp: search_params.start_timestamp,
        end_timestamp: search_params.end_timestamp,
        query_ast: query_ast_json,
        limit: None,
    })
}

#[cfg(test)]
mod tests {
    use serde_json::json;

    use super::*;

    #[test]

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Check the index_filter JSON in the request is well-formed
  2. If you develop custom QueryAst nodes, verify their Serialize/Deserialize impls round-trip
  3. Pin/align quickwit-query versions across the workspace
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the index_filter body before the request:
let ast = serde_json::from_value::<serde_json::Value>(index_filter)?; // must be valid JSON
if !index_filter.is_object() { return Err(ElasticsearchError::invalid_argument("index_filter")); }

Try / catch

// Callers of the list-fields ES API:
match resp {
    Ok(fields) => fields,
    Err(e) if e.status() == 400 => { /* fix index_filter JSON and retry */ }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: build_list_field_request_for_es_api with an index_filter whose QueryAst serde implementation fails (non-serializable value in a custom/new AST node).

Common situations: Adding new QueryAst node types without deriving/implementing Serialize correctly; extremely large or malformed index_filter bodies that hit serde limits.

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


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/f0df9c50c51b989d. Report an issue: GitHub.