microsoft/aspire · error · InvalidOperationException

Duplicate span id ' ' detected.

Error message

Duplicate span id '{span.SpanId}' detected.

What it means

OtlpTrace.AddSpan enforces that each span id appears at most once within a trace. Since spans are kept in a list keyed/checked by SpanId, inserting a duplicate would corrupt the trace structure (double-counted nodes, broken depth/duration calculations). AddSpan throws this InvalidOperationException when the incoming span's SpanId already exists in Spans.

Solutions

  1. Deduplicate spans before export/at the collector so each SpanId is sent once per trace.
  2. On the ingestion side, check trace.Spans for the id before calling AddSpan, or skip spans already present.
  3. Investigate exporter retry configuration: enable idempotent delivery or reduce aggressive retries that resend identical batches.

Example fix

// before
trace.AddSpan(span);
// after
if (!trace.Spans.Contains(span.SpanId))
{
    trace.AddSpan(span);
}
Defensive patterns

Strategy: validation

Validate before calling

// check before inserting
if (trace.Spans.Any(s => s.SpanId == span.SpanId)) return; // skip duplicate

Try / catch

try
{
    trace.AddSpan(span);
}
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Duplicate span id"))
{
    logger.LogWarning(ex, "Ignoring duplicate span {SpanId}.", span.SpanId);
}

Prevention

When it happens

Trigger: AddSpan throws when Spans.Contains(span.SpanId) is true. Happens while materializing or adding OTLP spans (Clone, MaterializeTraces, filter paths) when the same span is delivered twice, e.g. duplicate exports from a retrying exporter or the same batch processed twice.

Common situations: OTLP exporter retries re-sending a batch after a timeout, producing duplicate span ids on the server; a collector delivering overlapping batches; test code calling AddSpan twice with the same span; replay of stored telemetry without deduplication.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/e7e156395e568883. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Dashboard/Otlp/Model/OtlpTrace.cs:44

    public int CalculateDepth(OtlpSpan span)
    {
        var depth = 0;
        var currentSpan = span;
        while (currentSpan != null)
        {
            depth++;
            currentSpan = currentSpan.GetParentSpan();
        }
        return depth;
    }

    public int CalculateMaxDepth() => Spans.Max(CalculateDepth);

    public void AddSpan(OtlpSpan span, bool skipLastUpdatedDate = false)
    {
        if (Spans.Contains(span.SpanId))
        {
            throw new InvalidOperationException($"Duplicate span id '{span.SpanId}' detected.");
        }

        var insertIndex = 0;
        for (var i = Spans.Count - 1; i >= 0; i--)
        {
            if (span.StartTime > Spans[i].StartTime)
            {
                insertIndex = i + 1;
                break;
            }
        }
        Spans.Insert(insertIndex, span);

        if (HasCircularReference(span))
        {
            Spans.Remove(span);
            throw new InvalidOperationException($"Circular loop detected for span '{span.SpanId}' with parent '{span.ParentSpanId}'.");
        }

View on GitHub (pinned to 25830f84bd)