jaegertracing/jaeger · warning

maxTracesPerSecond is higher than int16

Error message

maxTracesPerSecond is higher than int16

What it means

convertRateLimitingFromDomain returns this error when the domain model's MaxTracesPerSecond exceeds math.MaxInt16. The Thrift (jaeger-api_v2 to legacy thrift) representation stores the rate as int16, so larger values cannot be represented and would silently truncate.

Source

Thrown at internal/converter/thrift/jaeger/sampling_from_domain.go:45

		RateLimitingSampling:  rl,
		OperationSampling:     convertPerOperationFromDomain(r.GetOperationSampling()),
	}
	return thriftResp, nil
}

func convertProbabilisticFromDomain(s *api_v2.ProbabilisticSamplingStrategy) *sampling.ProbabilisticSamplingStrategy {
	if s == nil {
		return nil
	}
	return &sampling.ProbabilisticSamplingStrategy{SamplingRate: s.GetSamplingRate()}
}

func convertRateLimitingFromDomain(s *api_v2.RateLimitingSamplingStrategy) (*sampling.RateLimitingSamplingStrategy, error) {
	if s == nil {
		return nil, nil
	}
	if s.MaxTracesPerSecond > math.MaxInt16 {
		return nil, errors.New("maxTracesPerSecond is higher than int16")
	}
	return &sampling.RateLimitingSamplingStrategy{
		//nolint:gosec // G115
		MaxTracesPerSecond: int16(s.GetMaxTracesPerSecond()),
	}, nil
}

func convertPerOperationFromDomain(s *api_v2.PerOperationSamplingStrategies) *sampling.PerOperationSamplingStrategies {
	if s == nil {
		return nil
	}
	r := &sampling.PerOperationSamplingStrategies{
		DefaultSamplingProbability:       s.GetDefaultSamplingProbability(),
		DefaultLowerBoundTracesPerSecond: s.GetDefaultLowerBoundTracesPerSecond(),
		DefaultUpperBoundTracesPerSecond: &s.DefaultUpperBoundTracesPerSecond,
	}

	perOp := s.GetPerOperationStrategies()

View on GitHub (pinned to 806f444784)

Solutions

  1. Lower the sampler's MaxTracesPerSecond to <= 32767 (32767 spans/sec is far beyond typical client needs)
  2. Return an out-of-range value from your own strategy provider so the default (e.g. 1000) is used instead
  3. Handle the returned error upstream by falling back to a default strategy rather than crashing the sampling response

Example fix

// before
strategy := &api_v2.RateLimitingSamplingStrategy{MaxTracesPerSecond: 100000}
// after
strategy := &api_v2.RateLimitingSamplingStrategy{MaxTracesPerSecond: 1000} // must fit int16
Defensive patterns

Strategy: validation

Validate before calling

if s.MaxTracesPerSecond > math.MaxInt16 {
    s.MaxTracesPerSecond = math.MaxInt16 // or reject before converting
}
resp, err := jaegerconv.ConvertSamplingResponseFromDomain(strategy)
if err != nil {
    // fall back to default strategy
}

Type guard

func fitsInt16(v int32) bool {
    return v >= math.MinInt16 && v <= math.MaxInt16
}

Try / catch

resp, err := ConvertSamplingResponseFromDomain(s)
if err != nil {
    if strings.Contains(err.Error(), "higher than int16") {
        return defaultStrategy(), nil
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling ConvertSamplingResponseFromDomain with a RateLimitingSamplingStrategy whose MaxTracesPerSecond > 32767; convertRateLimitingFromDomain performs the explicit range check and errors instead of narrowing.

Common situations: Custom adaptive sampling backends producing very high rate-limit values; misconfigured rate limits entered as, e.g., 100000 traces/sec; converters used in dual-protocol collectors bridging OTLP-era domain types to legacy Thrift clients.

Related errors


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