dbt-labs/dbt-core · error

expected `exclude` sequence in serialized atom

Error message

expected `exclude` sequence in serialized atom

What it means

Test assertion "expected `exclude` sequence in serialized atom" panics in test_serialize_atom_with_nested_exclude when the serialized YAML for a selection atom has an `exclude` key that is not a YAML sequence. The test verifies that a method/union selector with nested exclude serializes exclude as a single-element list wrapping the union.

Source

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

            None,
            None,
            Some(dbt_common::node_selector::IndirectSelection::default()),
            Some(Box::new(SelectExpression::Or(vec![
                atom(MethodName::Tag, "usage"),
                atom(MethodName::Tag, "feed_service_now"),
            ]))),
        ));

        let yaml = select_expression_to_yaml(&expr);

        assert_eq!(yaml.get("method").and_then(|v| v.as_str()), Some("fqn"));
        assert_eq!(yaml.get("value").and_then(|v| v.as_str()), Some("*"));

        // `exclude` must be a single-element list wrapping the union.
        let exclude = yaml
            .get("exclude")
            .and_then(|v| v.as_sequence())
            .expect("expected `exclude` sequence in serialized atom");
        assert_eq!(exclude.len(), 1);

        let union = exclude[0]
            .get("union")
            .and_then(|v| v.as_sequence())
            .expect("expected `union` sequence inside exclude");
        let mut tags: Vec<String> = union
            .iter()
            .map(|item| {
                assert_eq!(item.get("method").and_then(|v| v.as_str()), Some("tag"));
                item.get("value")
                    .and_then(|v| v.as_str())
                    .unwrap()
                    .to_string()
            })
            .collect();
        tags.sort();
        assert_eq!(tags, vec!["feed_service_now", "usage"]);

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Print the serialized YAML in the test to inspect the actual exclude shape.
  2. Fix the serializer so exclude emits as a sequence wrapping the nested union.
  3. Update the test expectations only if the new serialization format is intentional.

Example fix

// before
exclude: {union: [a, b]}
// after
exclude:
  - union: [a, b]
Defensive patterns

Strategy: type-guard

Validate before calling

// assert serialized shape before parsing in consumers
if !yaml.get("exclude").map_or(false, |v| v.is_sequence()) {
    eprintln!("exclude is not a sequence: {:?}", yaml.get("exclude"));
}

Type guard

fn exclude_is_sequence(yaml: &serde_yaml::Value) -> bool { yaml.get("exclude").map_or(false, |v| v.is_sequence()) }

Prevention

When it happens

Trigger: The selector atom serializer changed shape — e.g., emitting `exclude: {union: [...]}` (a map) or omitting exclude — so `.as_sequence()` returns None in the test.

Common situations: A refactor of SelectorAtom serialization (serde attributes like flatten/untagged) altering the exclude representation; YAML tagged vs untagged union output change.

Related errors


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