dbt-labs/dbt-core · error

Error message always present on ShouldBe::ButIsnt variant

Error message

Error message always present on ShouldBe::ButIsnt variant

What it means

A panic from `.expect()` in `try_new` while validating dbt_project.yml/properties keys. When a key's deserialization fails with a `ShouldBe::ButIsnt` variant, the code expects an error message to always be present so it can rewrite the generic 'expected struct ...' message into 'Unrecognized key ...'. The panic means that invariant (ButIsnt always carries a message) was violated by the serde machinery.

Source

Thrown at crates/dbt-parser/src/dbt_project_config.rs:104

                            detail
                        ),
                    );
                    emit_strict_parse_error(fs_err, dependency_package_name);
                }
                ShouldBe::ButIsnt(_) => {
                    let filename = if let Some(raw) = variant.as_ref_raw()
                        && let Some(filename) = raw.span().get_filename()
                    {
                        Some(filename)
                    } else {
                        None
                    };

                    // An unknown key produces the error message `expected struct <SelfType>` due to
                    // the recursive type. Catch the error here to inject a more descriptive error.
                    let err_msg = variant
                        .as_err_msg()
                        .expect("Error message always present on ShouldBe::ButIsnt variant");
                    let self_type = std::any::type_name::<S>()
                        .rsplit("::")
                        .next()
                        .unwrap_or_default();
                    let detail = if err_msg.contains(&format!("expected struct {self_type}")) {
                        format!("Unrecognized key `{key_path}`. Custom keys must go under `+meta`.")
                    } else {
                        err_msg.to_string()
                    };

                    let err = variant
                        .take_err()
                        .expect("Error always present on ShouldBe::ButIsnt variant");
                    let fs_err = yaml_to_fs_error(err, filename).with_context(format!(
                        "Invalid {} definition `{}`: {}",
                        S::type_name(),
                        key_path,
                        detail

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Report/debug the serde helper: ensure every `ShouldBe::ButIsnt` is constructed with an error message
  2. Inspect which key/type triggered it by reproducing with the same YAML and struct type
  3. Pin/upgrade `dbt-jinja-utils` to a version where the ButIsnt invariant holds
  4. As a workaround, wrap config parsing so the panic is converted into a proper error report

Example fix

// before
let err_msg = variant.as_err_msg().expect("Error message always present on ShouldBe::ButIsnt variant");

// after
let err_msg = variant.as_err_msg().unwrap_or_else(|| "invalid value".to_string());
Defensive patterns

Strategy: fallback

Try / catch

let err_msg = match variant.as_err_msg() {
    Some(m) => m,
    None => return Err(fallback_error("unrecognized key")),
};

Prevention

When it happens

Trigger: Deserializing a config struct `S` from YAML where an unknown/invalid key yields a `ShouldBe::ButIsnt` variant whose `as_err_msg()` returns None — a serde-layer invariant breach, not a user config problem.

Common situations: Practically only hit after internal changes to `dbt_jinja_utils::serde`'s ShouldBe/err plumbing, or via unusual deserializer paths that construct ButIsnt without a message while processing dbt_project.yml keys.

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