dbt-labs/dbt-core · error

inline exclude should remain inside union

Error message

inline exclude should remain inside union

What it means

Test-only assertion in test_manifest_selector_preserves_mixed_union_with_selector_reference: a union mixing plain values and selector references must still serialize as a plain union with inline exclude, not force whole-expression AST serialization. Fires if mixed unions regress to AST output.

Solutions

  1. Fix the definition-preservation heuristic for unions containing selector references
  2. Keep the mixed-union fixture in the suite
  3. Treat failure as a manifest serialization regression
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/dbt-parser/src/resolve/resolve_selectors.rs:836 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at crates/dbt-parser/src/resolve/resolve_selectors.rs:836

            definition.get("intersection").is_none(),
            "mixed selector references must not force whole-expression AST serialization"
        );
        let union = definition
            .get("union")
            .and_then(|value| value.as_sequence())
            .expect("manifest should preserve original union");
        assert_eq!(union.len(), 3);
        assert_eq!(
            union[0].get("method").and_then(|v| v.as_str()),
            Some("selector")
        );
        assert_eq!(union[0].get("value").and_then(|v| v.as_str()), Some("base"));
        assert_eq!(union[1].get("method").and_then(|v| v.as_str()), Some("fqn"));
        assert_eq!(union[1].get("value").and_then(|v| v.as_str()), Some("d"));
        let exclude = union[2]
            .get("exclude")
            .and_then(|value| value.as_sequence())
            .expect("inline exclude should remain inside union");
        assert_eq!(exclude[0].get("value").and_then(|v| v.as_str()), Some("e"));
        Ok(())
    }

    #[test]
    fn test_manifest_selector_preserves_pure_selector_alias() -> FsResult<()> {
        let mut selector_ref = BTreeMap::new();
        selector_ref.insert("selector".to_string(), SelectorValue::from("base").into());
        let original_definition =
            SelectorDefinitionValue::Full(SelectorExpr::Atom(AtomExpr::MethodKey(selector_ref)));
        let normalized_include = SelectExpression::And(vec![
            SelectExpression::Or(vec![atom(MethodName::Fqn, "a"), atom(MethodName::Fqn, "b")]),
            SelectExpression::Exclude(Box::new(atom(MethodName::Fqn, "c"))),
        ]);
        let resolved_selectors = HashMap::from([(
            "alias".to_string(),
            SelectorEntry {
                include: normalized_include,

View on GitHub (pinned to 0267ce9170)