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,
detailView on GitHub (pinned to 0267ce9170)
Solutions
- Report/debug the serde helper: ensure every `ShouldBe::ButIsnt` is constructed with an error message
- Inspect which key/type triggered it by reproducing with the same YAML and struct type
- Pin/upgrade `dbt-jinja-utils` to a version where the ButIsnt invariant holds
- 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
- Keep dbt-jinja-utils and dbt-parser versions in sync
- Validate dbt_project.yml keys (+prefixed) before parsing in CI
- Report ShouldBe invariant breaches upstream instead of patching locally
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
- Error always present on ShouldBe::ButIsnt variant
- Should be able to serialize job labels
- yaml deserializes into config type
- ModelPropertiesEntry guaranteed to exist for model
- Schema not found for canonical FQN: {}
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/f563815d40ab23de.
Report an issue: GitHub.