dbt-labs/dbt-core · error

span is required

Error message

span is required

What it means

`MacroInfo` construction in the manifest macro-deserialization path panics via `inner_macro.span.expect("span is required")`. The library assumes every macro parsed into an `InnerMacro` carries a resolved source span; a macro reaching this aggregation entry without one indicates the parser or a deserialization boundary dropped the span. The panic aborts manifest building rather than producing a macro with unknown location.

Source

Thrown at crates/dbt-schemas/src/schemas/macros.rs:119

}

pub fn build_macro_units(
    nodes: &BTreeMap<String, DbtMacro>,
    project_root: &Path,
) -> BTreeMap<String, Vec<MacroUnit>> {
    let mut macros = BTreeMap::new();
    for (_, inner_macro) in nodes.iter() {
        let display_path = inner_macro
            .get_node_path(NodePathKind::Definition, project_root, project_root)
            .into_owned();
        macros
            .entry(inner_macro.package_name.clone())
            .or_insert(vec![])
            .push(MacroUnit {
                info: MacroInfo {
                    name: inner_macro.name.clone(),
                    path: display_path,
                    span: inner_macro.span.expect("span is required"),
                    funcsign: inner_macro.funcsign.clone(),
                    args: inner_macro.args.clone(),
                    unique_id: inner_macro.unique_id.clone(),
                    name_span: inner_macro.macro_name_span.expect("name_span is required"),
                },
                sql: inner_macro.macro_sql.clone(),
            });
    }
    macros
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_macro_config_default_serializes_docs_with_nulls() {
        // serialize_docs_with_nulls forces both fields to be present, including

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Ensure the macro goes through the normal parse path so its span is extracted from the source file before manifest aggregation
  2. When loading macros from a serialized artifact, regenerate the artifact with a matching dbt version so spans are present
  3. Patch the construction site to set `span` explicitly (or fall back to a zero/unknown span) if you build `InnerMacro` programmatically

Example fix

// before
span: inner_macro.span.expect("span is required"),
// after
span: inner_macro.span.unwrap_or_default(),
Defensive patterns

Strategy: validation

Validate before calling

// before manifest aggregation
if inner_macro.span.is_none() {
    return Err(/* error: macro {} has no span; re-parse its source file */);
}

Type guard

fn has_span(m: &InnerMacro) -> bool { m.span.is_some() && m.macro_name_span.is_some() }

Try / catch

// wrap manifest building; panics surface as process aborts, so guard at the call site
let result = std::panic::catch_unwind(|| build_macros(resolver_state));

Prevention

When it happens

Trigger: Calling the macro-manifest build function with an `InnerMacro` whose `span: Option<Span>` is `None` — typically a macro loaded from a deserialized/partial context (e.g. a macro built programmatically or from a cached artifact that omitted spans) instead of one that went through full parsing.

Common situations: Consuming a manifest or macro artifact produced by an older/newer dbt version that did not serialize spans; constructing `InnerMacro` values in custom tooling or tests without setting `span`; a parser bug where `macro_sql`/`unique_id` are set but span extraction failed.

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/69784918cead1d6c. Report an issue: GitHub.