dbt-labs/dbt-core · error

Error always present on ShouldBe::ButIsnt variant

Error message

Error always present on ShouldBe::ButIsnt variant

What it means

A panic from `.expect()` in `try_new` immediately after the message rewrite: the code takes ownership of the error (`take_err()`) stored on a `ShouldBe::ButIsnt` variant and asserts it is always present. This error is then converted into a richer `Invalid <type> definition` fs error. The panic signals the same ShouldBe invariant was broken at the error-value level.

Source

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

                    // 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
                    ));
                    emit_strict_parse_error(fs_err, dependency_package_name);
                }
            }
        };
        if !disallow_plus_prefix {
            warn_plus_prefixed_resource_paths::<S>("", configs, "", false);
        }
        Ok(recur_build_dbt_project_config(
            dbt_config,
            configs,
            "",
            &on_error,

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Fix the producer so ButIsnt always carries an Err value
  2. Reproduce with the offending YAML key to identify which deserializer drops the error
  3. Upgrade/pin dbt-jinja-utils to a fixed version
  4. Replace the expect with a graceful fallback error to keep config parsing failing with a report instead of panicking

Example fix

// before
let err = variant.take_err().expect("Error always present on ShouldBe::ButIsnt variant");

// after
let err = variant.take_err()
    .unwrap_or_else(|| DbtError::new(ErrorCode::InvalidConfigError, "invalid value"));
Defensive patterns

Strategy: fallback

Try / catch

let err = variant.take_err().unwrap_or_else(|| {
    DbtError::new(ErrorCode::InvalidConfigError, "invalid value")
});

Prevention

When it happens

Trigger: Same path as the sibling expect: YAML config key deserialization produces `ShouldBe::ButIsnt` whose `take_err()` returns None while building the 'Invalid <S::type_name> definition' error.

Common situations: Only observed when internal serde plumbing constructs ButIsnt without carrying an error; typically after refactors of dbt_jinja_utils::serde or custom deserializers feeding project config parsing.

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