jaegertracing/jaeger · error
%w: %w
Error message
%w: %w
What it means
validateQuery rejects trace queries that lack a service name by wrapping ErrServiceNameNotSet together with errors.ErrUnsupported (double %w, Go 1.20 multi-error wrapping). The Cassandra index is partitioned by service, so a service-less query cannot be executed — it would scan an empty partition and be indistinguishable from 'no traces found'.
Source
Thrown at internal/storage/v1/cassandra/spanstore/reader.go:227
return spans, nil
}
// GetTrace takes a traceID and returns the spans associated with that traceID
func (s *SpanReader) GetTrace(ctx context.Context, traceID dbmodel.TraceID) ([]dbmodel.Span, error) {
return s.readTrace(ctx, traceID)
}
func validateQuery(p *tracestore.TraceQueryParams) error {
if p == nil {
return ErrMalformedRequestObject
}
// Every index is keyed by service name, so a query without one has no partition to
// read: queryByService would run with an empty partition key and return zero rows,
// which is indistinguishable from "no matching traces". Refusing it says what is
// actually true (RFC 0013 §3.3); the query service normally rejects such a query
// first, from the capability this reader declares.
if p.ServiceName == "" {
return fmt.Errorf("%w: %w", ErrServiceNameNotSet, errors.ErrUnsupported)
}
if p.StartTimeMin.IsZero() || p.StartTimeMax.IsZero() {
return ErrStartAndEndTimeNotSet
}
if !p.StartTimeMin.IsZero() && !p.StartTimeMax.IsZero() && p.StartTimeMax.Before(p.StartTimeMin) {
return ErrStartTimeMinGreaterThanMax
}
if p.DurationMin != 0 && p.DurationMax != 0 && p.DurationMin > p.DurationMax {
return ErrDurationMinGreaterThanMax
}
if (p.DurationMin != 0 || p.DurationMax != 0) && p.Attributes.Len() > 0 {
return ErrDurationAndTagQueryNotSupported
}
return nil
}
// FindTraces retrieves traces that match the traceQuery
func (s *SpanReader) FindTraces(ctx context.Context, traceQuery *tracestore.TraceQueryParams) iter.Seq2[dbmodel.Trace, error] {View on GitHub (pinned to 806f444784)
Solutions
- Set Query.ServiceName to a non-empty value before calling FindTraceIDs/FindTraces.
- Check errors.Is(err, ErrServiceNameNotSet) and errors.Is(err, errors.ErrUnsupported) to detect this case programmatically and prompt the user for a service.
- If you need service-less searches, use a backend/index that supports them (e.g. Elasticsearch/OpenSearch storage) rather than Cassandra.
- Update calling code to rely on the query service's capability check so the query is validated before reaching storage.
Example fix
// before
spans, err := reader.FindTraceIDs(ctx, tracestore.Query{StartTimeMin: t1, StartTimeMax: t2})
// after
spans, err := reader.FindTraceIDs(ctx, tracestore.Query{ServiceName: "frontend", StartTimeMin: t1, StartTimeMax: t2}) Defensive patterns
Strategy: validation
Validate before calling
if q.ServiceName == "" {
return errors.New("Query.ServiceName is required for Cassandra trace queries")
}
if q.StartTimeMin.IsZero() || q.StartTimeMax.IsZero() {
return errors.New("Query start/end times are required")
}
if q.StartTimeMax.Before(q.StartTimeMin) {
return errors.New("StartTimeMax must not be before StartTimeMin")
} Type guard
func isValidQuery(q tracestore.Query) bool {
return q.ServiceName != "" && !q.StartTimeMin.IsZero() && !q.StartTimeMax.IsZero() && !q.StartTimeMax.Before(q.StartTimeMin)
} Try / catch
ids, err := reader.FindTraceIDs(ctx, q)
if err != nil {
if errors.Is(err, spanstore.ErrServiceNameNotSet) || errors.Is(err, errors2.ErrUnsupported) {
// surface 'service name required' to the caller
}
return err
} Prevention
- Always populate ServiceName before querying Cassandra storage.
- Use errors.Is against ErrServiceNameNotSet/ErrUnsupported for precise handling.
- Rely on the query service's capability checks to filter unsupported queries early.
- Validate time range order alongside service name in client code.
When it happens
Trigger: Calling FindTraceIDs (or FindTraces) with tracestore.Query where ServiceName == ""; also asserted in TestTraceQueryParameterValidation. The query service normally blocks this earlier via declared capabilities, but direct storage clients hit it here.
Common situations: Custom tooling or tests invoking SpanReader.FindTraceIDs directly without filling Query.ServiceName; UI/API regressions that drop the service parameter; scripts built against other backends that allow global queries.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- error reading operation_names from storage: %w
- error reading %s from storage: %w
- error reading service_names from storage: %w
- %w: it cannot be combined with %v; express those predicates
- trace_id is required
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/a5da5613f4307bcd.
Report an issue: GitHub.