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 did

View on GitHub (pinned to 806f444784)

Solutions

  1. Fix the filter value so it matches the field's expected type/format
  2. Run the filter through validation (EnsureFilterStandsAlone / structural checks) before issuing the query
  3. 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

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


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/f9e779586ff8000a. Report an issue: GitHub.