jaegertracing/jaeger · error

cannot send the query filter: %w

Error message

cannot send the query filter: %w

What it means

toProtoQueryParameters converts tracestore.TraceQueryParams (including its Filter expression tree) into the wire proto. If the filter expression cannot be represented in the protobuf form (expressionproto.ToProto fails), conversion aborts with this error rather than silently dropping predicates — a filter-less query would read to the server as an unrestricted search.

Source

Thrown at internal/storage/v2/grpc/tracereader.go:266

			MinStartTime:      jptrace.UnixNanoToTime(ps.GetMinStartTimeUnixNano()),
			MaxEndTime:        jptrace.UnixNanoToTime(ps.GetMaxEndTimeUnixNano()),
			SpanCount:         int(ps.GetSpanCount()),
			ErrorSpanCount:    int(ps.GetErrorSpanCount()),
			OrphanSpanCount:   int(ps.GetOrphanSpanCount()),
			Services:          svcs,
		}
	}
	return batch
}

// toProtoQueryParameters encodes a query for the remote server. Encoding the filter can fail, for
// a tree the wire has no form for, and asking here rather than at each RPC keeps that one refusal in
// one place: the alternative is sending a query whose filter went missing, which reads to the server
// as a search with no predicates.
func toProtoQueryParameters(t tracestore.TraceQueryParams) (*storage.TraceQueryParameters, error) {
	filter, err := expressionproto.ToProto(t.Filter)
	if err != nil {
		return nil, fmt.Errorf("cannot send the query filter: %w", err)
	}
	return &storage.TraceQueryParameters{
		ServiceName:   t.ServiceName,
		OperationName: t.OperationName,
		Attributes:    convertMapToKeyValueList(t.Attributes),
		StartTimeMin:  t.StartTimeMin,
		StartTimeMax:  t.StartTimeMax,
		DurationMin:   t.DurationMin,
		DurationMax:   t.DurationMax,
		SearchDepth:   int32(t.SearchDepth), //nolint:gosec // G115
		Filter:        filter,
	}, nil
}

func convertMapToKeyValueList(m pcommon.Map) []*storage.KeyValue {
	keyValues := make([]*storage.KeyValue, 0, m.Len())
	m.Range(func(k string, v pcommon.Value) bool {
		keyValues = append(keyValues, &storage.KeyValue{

View on GitHub (pinned to 806f444784)

Solutions

  1. Inspect the wrapped ToProto error to find the unsupported expression node
  2. Simplify or remove unsupported operators from the filter
  3. Express unsupported predicates as attribute filters if possible
  4. Upgrade to a client/proto version supporting the expression form

Example fix

// before
params.Filter = unsupportedExpr // e.g. unknown operator tree
// after
params.Filter = expr.And(expr.Eq("service.name", "svc"), expr.Gt("duration", n)) // supported forms only
Defensive patterns

Strategy: validation

Validate before calling

if t.Filter != nil {
    if err := exprValidateSupportedOperators(t.Filter); err != nil {
        return fmt.Errorf("filter not sendable: %w", err)
    }
}

Type guard

func sendableFilter(f expression.Filter) bool {
    ok, err := expressionproto.ToProto(f) == nil // probe conversion
    return ok && err == nil
}

Prevention

When it happens

Trigger: Passing TraceQueryParams with a Filter whose expression tree has no proto representation (unsupported operators, malformed/nested expressions) into FindTraces, FindTraceIDs, or FindTraceSummaries via toProtoQueryParameters.

Common situations: Using filter operators not yet supported by the proto schema; constructing expressions programmatically with invalid nesting; version mismatch where client expressions exceed server wire capabilities.

Related errors


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