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, includingView on GitHub (pinned to 0267ce9170)
Solutions
- Ensure the macro goes through the normal parse path so its span is extracted from the source file before manifest aggregation
- When loading macros from a serialized artifact, regenerate the artifact with a matching dbt version so spans are present
- 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
- Always construct macros through the standard parser path
- Avoid deserializing macro artifacts across dbt version boundaries
- Add a debug_assert!(inner_macro.span.is_some()) early to fail fast with context
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
- name_span is required
- root manifest path config missing
- manifest path config missing for manifest node package
- DbtQuoting should be set
- Unknown or unsupported adapter type
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/69784918cead1d6c.
Report an issue: GitHub.