jaegertracing/jaeger · warning · ErrFilterDisabled

%w: enable the %q feature gate to use it

Error message

%w: enable the %q feature gate to use it

What it means

ErrFilterDisabled is returned when a trace search carries a structured query filter but the StructuredFilters feature gate is not enabled on the jaeger-query service. The gate check runs before any backend capability check because the refusal is purely local. Clients can detect it via querysvc.IsBadRequest (400-class) rather than treating it as a server fault.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/querysvc/service.go:208

// prepareSearchQuery settles a search before it is dispatched: it refuses a request this
// deployment does not accept, gives the configured query interceptors their say, and returns the
// query to dispatch in the shape the backend understands, along with the context to dispatch it
// with. One place decides, so that every caller gets the same answer instead of each backend's
// own (ADR-013).
//
// The interceptors run after the caller's request is validated and before the backend's
// capabilities are consulted. So an interceptor is never shown a request jaeger-query was going
// to refuse anyway, and a predicate an interceptor adds is held to the same capability check as
// one the caller sent.
func (qs QueryService) prepareSearchQuery(
	ctx context.Context,
	query TraceQueryParams,
) (context.Context, TraceQueryParams, error) {
	if query.Filter != nil {
		// None of these refusals depends on the backend, so they come before the capability call
		// rather than after it.
		if !StructuredFiltersGate.IsEnabled() {
			return ctx, query, fmt.Errorf("%w: enable the %q feature gate to use it",
				ErrFilterDisabled, StructuredFiltersGate.ID())
		}
		if err := query.EnsureFilterStandsAlone(); err != nil {
			return ctx, query, err
		}
		// Decoding a filter validates nothing, so it is finalized — validated and normalized —
		// here, on behalf of every API layer above (RFC 0005 §7).
		finalized, err := expression.Finalize(query.Filter)
		if err != nil {
			return ctx, query, fmt.Errorf("%w: %w", tracestore.ErrFilterInvalid, err)
		}
		query.Filter = finalized
	}
	if len(qs.options.Interceptors) > 0 {
		var err error
		ctx, query, err = qs.onQuery(ctx, query)
		if err != nil {
			return ctx, query, err

View on GitHub (pinned to 806f444784)

Solutions

  1. Enable the feature gate whose ID appears in the message on the jaeger-query extension configuration and restart.
  2. If the gate cannot be enabled yet, have clients stop sending the filter field in search requests.
  3. Check errors.Is(err, querysvc.ErrFilterDisabled) client-side to surface a clear 400 message instead of a generic failure.
  4. Verify all query replicas have the gate enabled to avoid inconsistent behavior behind a load balancer.

Example fix

// before (jaeger-query config)
jaeger_query:
  # structured filters gate not enabled
// after
jaeger_query:
  feature_gates:
    - <gate-id-from-error-message>
Defensive patterns

Strategy: validation

Validate before calling

if query.Filter != nil && !structuredFiltersGateEnabled {
    return fmt.Errorf("structured filters are disabled on this deployment: %w", querysvc.ErrFilterDisabled)
}

Try / catch

resp, err := client.FindTraces(ctx, query)
if err != nil && errors.Is(err, querysvc.ErrFilterDisabled) {
    // handle as HTTP 400: prompt user to enable the gate or drop the filter
    return badRequest(err)
}

Prevention

When it happens

Trigger: prepareSearchQuery (called during FindTraces) sees query.Filter != nil while StructuredFiltersGate.IsEnabled() is false — i.e. the client submitted a structured filter to a server started without the feature gate enabled.

Common situations: Jaeger UI/API client using the new structured-filter search against an older or gate-disabled jaeger-query deployment; operators upgrading the UI before enabling the gate on the server; feature-flag rollout where only some query instances have the gate on.

Related errors


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