jaegertracing/jaeger · error

cannot assign unique span ID, too many spans in the trace

Error message

cannot assign unique span ID, too many spans in the trace

What it means

errTypedConstant reports that a filter constant declares a type (via constantKind, by wire type) that this backend cannot route to a typed stored value, because all attribute values are indexed as keywords here. Honoring the declared type would silently match more than the user asked, so only untyped constants are served; the filter is rejected with tracestore.ErrFilterUnsupported. Typed attribute indexing (RFC 0015) is the roadmap fix.

Source

Thrown at cmd/jaeger/internal/extension/jaegerquery/internal/adjuster/spaniduniquifier.go:16

// Copyright (c) 2019 The Jaeger Authors.
// Copyright (c) 2017 Uber Technologies, Inc.
// SPDX-License-Identifier: Apache-2.0

package adjuster

import (
	"errors"

	"go.opentelemetry.io/collector/pdata/pcommon"
	"go.opentelemetry.io/collector/pdata/ptrace"

	"github.com/jaegertracing/jaeger/internal/jptrace"
)

var errTooManySpans = errors.New("cannot assign unique span ID, too many spans in the trace")

// DeduplicateClientServerSpanIDs returns an adjuster that changes span ids for server
// spans (i.e. spans with tag: span.kind == server) if there is another
// client span that shares the same span ID. This is needed to deal with
// Zipkin-style clients that reuse the same span ID for both client and server
// side of an RPC call. Jaeger UI expects all spans to have unique IDs.
//
// Any issues encountered during adjustment are recorded as warnings in the
// span.
func DeduplicateClientServerSpanIDs() Adjuster {
	return Func(func(traces ptrace.Traces) {
		adjuster := spanIDDeduper{
			spansByID: make(map[pcommon.SpanID][]ptrace.Span),
			maxUsedID: pcommon.NewSpanIDEmpty(),
		}
		adjuster.adjust(traces)
	})
}

View on GitHub (pinned to 806f444784)

Solutions

  1. Send the constant untyped (let the expression carry a plain string/untyped constant) so it matches the keyword-stored value.
  2. Enable or migrate to typed attribute indexing (RFC 0015) if exact typed matching is required.
  3. Catch errors.Is(err, tracestore.ErrFilterUnsupported) and surface that typed constants are not supported by this backend.

Example fix

// before
attr.status (typed int64) == 200
// after
attr.status == "200"
Defensive patterns

Strategy: validation

Validate before calling

func untypedConstant(e expression.Expression) bool {
    return constantKind(e) == "untyped" // only untyped constants are served
}

Try / catch

q, err := buildFilterQuery(...)
if errors.Is(err, tracestore.ErrFilterUnsupported) && strings.Contains(err.Error(), "untyped constants only") {
    // strip the declared type and resend the constant untyped
}

Prevention

When it happens

Trigger: Submitting a filter whose constant is explicitly typed (e.g. an int64/float64/bool-typed attribute value) from untypedText, fieldText, or lengthOfTime, where the backend cannot route to a typed value in a keyword-only index.

Common situations: Clients that always attach wire types to attribute values (protobuf defaults) hitting a keyword-only Elasticsearch mapping; filters migrated from typed backends (Cassandra with typed columns) to Elasticsearch; RFC 0005 §5.4 typed matching expectations.

Related errors


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