{"record":{"id":"69784918cead1d6c","repo":"dbt-labs/dbt-core","slug":"span-is-required","errorCode":null,"errorMessage":"span is required","messagePattern":"span is required","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-schemas/src/schemas/macros.rs","lineNumber":119,"sourceCode":"}\n\npub fn build_macro_units(\n    nodes: &BTreeMap<String, DbtMacro>,\n    project_root: &Path,\n) -> BTreeMap<String, Vec<MacroUnit>> {\n    let mut macros = BTreeMap::new();\n    for (_, inner_macro) in nodes.iter() {\n        let display_path = inner_macro\n            .get_node_path(NodePathKind::Definition, project_root, project_root)\n            .into_owned();\n        macros\n            .entry(inner_macro.package_name.clone())\n            .or_insert(vec![])\n            .push(MacroUnit {\n                info: MacroInfo {\n                    name: inner_macro.name.clone(),\n                    path: display_path,\n                    span: inner_macro.span.expect(\"span is required\"),\n                    funcsign: inner_macro.funcsign.clone(),\n                    args: inner_macro.args.clone(),\n                    unique_id: inner_macro.unique_id.clone(),\n                    name_span: inner_macro.macro_name_span.expect(\"name_span is required\"),\n                },\n                sql: inner_macro.macro_sql.clone(),\n            });\n    }\n    macros\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_macro_config_default_serializes_docs_with_nulls() {\n        // serialize_docs_with_nulls forces both fields to be present, including","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-schemas/src/schemas/macros.rs#L101-L137","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nspan: inner_macro.span.expect(\"span is required\"),\n// after\nspan: inner_macro.span.unwrap_or_default(),","handlingStrategy":"validation","validationCode":"// before manifest aggregation\nif inner_macro.span.is_none() {\n    return Err(/* error: macro {} has no span; re-parse its source file */);\n}","typeGuard":"fn has_span(m: &InnerMacro) -> bool { m.span.is_some() && m.macro_name_span.is_some() }","tryCatchPattern":"// wrap manifest building; panics surface as process aborts, so guard at the call site\nlet result = std::panic::catch_unwind(|| build_macros(resolver_state));","preventionTips":["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"],"tags":["macros","span","panic","manifest"],"backgroundTag":"internal-invariant-violation","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}