jaegertracing/jaeger · error
invalid query filter
Error message
invalid query filter
What it means
ErrFilterInvalid indicates a query filter whose comparison value does not fit the field it compares — for example a non-numeric string compared against a duration field. The filter AST deliberately does not carry types (RFC 0005 §6.1), so this semantic mistake cannot be caught by structural validation and is rejected at query-preparation time.
Source
Thrown at internal/storage/v2/api/tracestore/capabilities.go:26
"slices"
expression "github.com/jaegertracing/jaeger-idl/query/expression/v1"
)
// ErrFilterUnsupported is returned for a well-formed query filter that the storage cannot
// serve — a level it does not index, an operator it has not implemented, or a boolean
// structure a flat index cannot evaluate (RFC 0005 §7). The query is refused rather than
// approximated, so a caller never reads a narrower answer as the whole one. The query
// service returns it for the limits a Reader declared through FilterCapabilities, and a
// Reader returns it for the ones that declaration is too coarse to express — a built-in
// field of a level it serves but does not store, or an operator it serves on some
// references and not others.
var ErrFilterUnsupported = errors.New("this storage backend cannot serve this query filter")
// ErrFilterInvalid is returned for a query filter whose value does not fit the field it
// compares — the kind of mistake a structural check cannot catch, because the filter AST
// deliberately does not carry types (RFC 0005 §6.1).
var ErrFilterInvalid = errors.New("invalid query filter")
// SearchCapabilities describes how a Reader's search methods behave where backends
// differ: which TraceQueryParams fields may be omitted, which are honored exactly
// rather than approximated, and which combinations a backend cannot serve. Its zero
// value is the least capable reader, so a field added here leaves every existing
// implementation declaring the new capability unsupported.
//
// Fields to expect over time, each of which is a real divergence today:
//
// - Whether SearchDepth is an exact limit or a hint. jaeger.api_v3's
// TraceQueryParameters warns of search_depth that "some implementations might not
// support precise limits", so a caller cannot tell whether a short result set means
// that there are no more matches or that the backend stopped early.
// - Which duration-query combinations hold. Cassandra reads DurationMin/DurationMax
// from a separate duration_index table, and it cannot combine that table with the
// tag index in one query, so it rejects a search that uses both
// (docs/adr/001-cassandra-find-traces-duration.md). The API layer stopped rejecting
// the combination in https://github.com/jaegertracing/jaeger/issues/1047, which didView on GitHub (pinned to 806f444784)
Solutions
- Fix the filter value so it matches the field's expected type/format
- Run the filter through validation (EnsureFilterStandsAlone / structural checks) before issuing the query
- Validate user-supplied filter values at the API boundary before constructing filter AST nodes
Example fix
// before
filter.Eq(field.Duration, "fast") // not a valid duration
// after
filter.Gt(field.Duration, mustParseDuration("1s")) Defensive patterns
Strategy: validation
Validate before calling
if err := tracestore.EnsureFilterStandsAlone(f); err != nil {
return fmt.Errorf("rejecting query: %w", err)
} Type guard
func validDurationValue(v any) bool {
switch v.(type) {
case time.Duration, string:
return true
}
return false
} Try / catch
res, err := reader.Search(ctx, q)
if errors.Is(err, tracestore.ErrFilterInvalid) {
return http.StatusBadRequest // invalid filter value, fix the caller's input
} Prevention
- Validate user-supplied filter values at the API boundary
- Parse durations/numbers explicitly before putting values into filter AST nodes
- Test queries through prepareSearchQuery/EnsureFilterStandsAlone in CI
When it happens
Trigger: Calling search/query with a filter whose value has the wrong type or format for the compared field; prepareSearchQuery and EnsureFilterStandsAlone return it when the filter's value fails the field's expected shape.
Common situations: Building filters programmatically with untyped values from JSON/user input; typos in date/duration literals; passing ints where strings (or vice versa) are expected for a field.
Related errors
- this storage backend cannot serve this query filter
- trace not found
- trace_id is required
- start_time must be before end_time
- trace not found
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/f9e779586ff8000a.
Report an issue: GitHub.