jaegertracing/jaeger · error · ErrInterceptorFilter

%w: %w

Error message

%w: %w

What it means

ErrInterceptorFilter is wrapped when expression.Finalize fails on the filter returned by a query interceptor. Finalize validates and normalizes the expression; a failure means the interceptor produced a structurally invalid or ill-typed filter that Jaeger cannot compile into a storage query. The original Finalize error is chained via Go's multi-%w wrapping for errors.Is/As inspection.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/querysvc/interceptor.go:111

// not hand to storage. An interceptor builds its filter by hand, in code jaeger-query does not
// control, and a malformed tree is typically answered by a backend matching nothing rather than
// refusing — so a search meant to be narrowed would come back wrong with nothing to say why.
//
// It finalizes rather than only validates, so that an interceptor's predicate reaches storage as the
// equal of one a caller sent, having been through the same stage.
//
// A nil filter here is the one mistake that fails open: a search that arrived with predicates and
// leaves with none asks for every trace in the time range. Its caller returns before this point when
// there were no predicates to begin with, since a caller may legitimately search a time range and
// nothing else.
func finalizeInterceptorFilter(returned *expression.Call) (*expression.Call, error) {
	if returned == nil {
		return nil, fmt.Errorf("%w: it returned no filter for a query that had predicates, which "+
			"would widen the search to every trace in the time range", ErrInterceptorFilter)
	}
	finalized, err := expression.Finalize(returned)
	if err != nil {
		return nil, fmt.Errorf("%w: %w", ErrInterceptorFilter, err)
	}
	return finalized, nil
}

// interceptResults hands every batch of seq to the interceptors' OnResult in order, threading the
// context each returns into the next so that state can accumulate across a multi-batch result.
// An OnResult error ends the stream rather than yielding later batches, which could leak results
// the failed sanitize or redaction was meant to withhold.
//
// It wraps the batches as storage yielded them, before the query service aggregates and adjusts
// them, so an interceptor rewrites the traces the reader actually returned.
func (qs QueryService) interceptResults(
	ctx context.Context,
	seq iter.Seq2[[]ptrace.Traces, error],
) iter.Seq2[[]ptrace.Traces, error] {
	if len(qs.options.Interceptors) == 0 {
		return seq
	}

View on GitHub (pinned to 806f444784)

Solutions

  1. Inspect the chained Finalize error in the message for the exact structural problem.
  2. Fix the interceptor to build the filter using the expression package's public constructors only.
  3. Have the interceptor validate its expression (Finalize) itself before returning it to fail fast locally.
  4. Rebuild against the jaeger version in use if the expression API changed underneath.

Example fix

// before
return expression.NewCall(customFn, operandOfWrongType), nil
// after
return expression.NewCall(expression.EqFn, expression.NewStringField("service.name"), expression.NewStringLiteralValue("foo")), nil
Defensive patterns

Strategy: try-catch

Validate before calling

// inside interceptor before returning
if _, err := expression.Finalize(myCall); err != nil {
    return nil, fmt.Errorf("interceptor built invalid expression: %w", err)
}

Try / catch

if err != nil && errors.Is(err, querysvc.ErrInterceptorFilter) {
    var finErr error
    if errors.As(err, &finErr) {
        log.Printf("finalize failed inside interceptor filter: %v", finErr)
    }
    return err
}

Prevention

When it happens

Trigger: finalizeInterceptorFilter calls expression.Finalize(returned) on the interceptor's returned *expression.Call and Finalize returns an error — e.g. the interceptor built a Call with a wrong argument count, an unknown function, or mismatched operand types.

Common situations: Custom interceptor composing expression AST nodes by hand with incorrect types or arity; an interceptor forwarding a stale/partially built expression; version skew where the expression API changed shape between Jaeger versions.

Related errors


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