dbt-labs/dbt-core · error

Parent span must have a SpanStartInfo record in its extensio

Error message

Parent span must have a SpanStartInfo record in its extensions

What it means

This is an internal invariant panic in dbt-tracing's span-id lookup. When a child span or event has an unfiltered parent span, the parent's extensions must contain a DLSpanStartInfo record (inserted at span creation); if it does not, the layer's internal bookkeeping is broken, so the code calls unreachable!. Reaching this means a SpanStartInfo was never inserted or was removed from a live parent span's extensions.

Source

Thrown at crates/dbt-tracing/src/layers/data_layer.rs:978

        return None;
    };

    loop {
        // Create a block scope to limit the borrow of parent extensions
        {
            let parent_ext = parent.extensions();
            let parent_span_filter_mask = parent_ext
                .get::<FilterMask>()
                .copied()
                .unwrap_or_else(FilterMask::empty);

            // Check if this parent span was filtered out for this consumer
            if !parent_span_filter_mask.is_filtered(index) {
                // Found an unfiltered parent span for this consumer. Extract its span ID
                if let Some(parent_span_record) = parent_ext.get::<DLSpanStartInfo>() {
                    return Some(parent_span_record.0.span_id);
                } else {
                    unreachable!("Parent span must have a SpanStartInfo record in its extensions");
                }
            }
        }

        let Some(grand_parent) = parent.parent() else {
            // No parent span, so no active parent span ID
            return None;
        };

        parent = grand_parent;
    }
}

#[cfg(any(test, feature = "test-utils"))]
pub fn get_span_start_info_from_span(
    span: &SpanRef<'_, impl Subscriber + for<'lookup> LookupSpan<'lookup>>,
) -> Option<SpanStartInfo> {
    let span_ext = span.extensions();

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Verify all spans pass through the data layer's on_new_span so DLSpanStartInfo is inserted into extensions
  2. Check for custom layers that strip or replace span extensions
  3. Ensure the parent span belongs to the same tracing registry/dispatch and is not a synthetic or foreign span
  4. Update dbt-tracing and report a bug with a reproducer if the invariant still breaks

Example fix

// before (workaround is not direct; guard at call site)
let span_id = lookup_filtered_parent_span_id(parent, mask);
// after (defensive handling instead of unreachable)
if let Some(rec) = parent_ext.get::<DLSpanStartInfo>() {
    Some(rec.0.span_id)
} else {
    tracing::warn!("parent span missing DLSpanStartInfo; skipping parent id");
    None
}
Defensive patterns

Strategy: validation

Validate before calling

fn parent_has_span_info(parent: &tracing::span::Span) -> bool {
    parent.extensions().get::<DLSpanStartInfo>().is_some()
}

Type guard

if parent.extensions().get::<DLSpanStartInfo>().is_some() { /* safe to lookup */ }

Try / catch

// panic is not catchable in normal flow; guard before:
let span_id = parent_has_span_info(parent)
    .then(|| lookup_filtered_parent_span_id(parent, mask))
    .flatten();

Prevention

When it happens

Trigger: Calling on_new_span, on_close, or on_event where the parent span passed the consumer's filter mask but lacks a DLSpanStartInfo extension record in its extensions.

Common situations: Custom tracing layers or spans created outside the data layer's on_new_span path; manual extension manipulation; version mismatches where span creation no longer stores DLSpanStartInfo; spans whose extensions were cleared mid-flight.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/97a08dcc38851978. Report an issue: GitHub.