dbt-labs/dbt-core · error
conversion_type_params must exist for conversion metric
Error message
conversion_type_params must exist for conversion metric
What it means
Panic "conversion_type_params must exist for conversion metric" fires in resolve_top_level_metrics when a conversion metric's type_params.conversion_type_params is Some at the guard but the cloned/checked value is unexpectedly None at unwrap time — practically, this occurs when metric type is conversion but conversion_type_params was cleared or mis-constructed between the check and the expect.
Source
Thrown at crates/dbt-parser/src/resolve/resolve_metrics.rs:503
.cumulative_type_params
.clone()
.unwrap_or_default()
.metric;
if let Some(metric) = maybe_cumulative_metric {
vec![metric.name]
} else {
vec![]
}
}
MetricType::Conversion => {
if type_params.conversion_type_params.is_none() {
vec![]
} else {
let conversion_type_params = type_params
.conversion_type_params
.clone()
.expect("conversion_type_params must exist for conversion metric");
let base_metric_name =
conversion_type_params.base_metric.unwrap_or_default().name;
let conversion_metric_name = conversion_type_params
.conversion_metric
.unwrap_or_default()
.name;
if base_metric_name.is_empty() || conversion_metric_name.is_empty() {
vec![]
} else {
vec![base_metric_name, conversion_metric_name]
}
}
}
_ => vec![],
};
let unique_ids_of_nodes_depends_on: Vec<String> = names_of_nodes_depends_onView on GitHub (pinned to 0267ce9170)
Solutions
- Validate the conversion metric's YAML: ensure conversion_type_params with base_metric and conversion_metric are present.
- Replace the guard+expect with a single match/if-let that produces a proper schema error naming the metric.
- Check for any code path between the guard and the expect that resets conversion_type_params to None.
Example fix
// before
if type_params.conversion_type_params.is_none() { vec![] } else {
let ctp = type_params.conversion_type_params.clone().expect("...");
// after
match type_params.conversion_type_params.clone() {
Some(ctp) => { /* ... */ }
None => return Err(err![arg.ctxt, "conversion metric '{}' missing conversion_type_params", name]),
} Defensive patterns
Strategy: validation
Validate before calling
# validate conversion metric YAML before dbt parse
# metrics:
# - name: conv
# type: conversion
# type_params:
# conversion_type_params:
# base_metric: {name: base}
# conversion_metric: {name: conv_metric}
# window: {count: 7, period: day}
assert 'conversion_type_params' in metric['type_params'] Prevention
- Always define base_metric, conversion_metric, and window for conversion metrics
- Run dbt parse (schema check) before deeper pipelines
- Prefer match over is_none-check + expect for Option fields
When it happens
Trigger: Defining a metric with `type: conversion` whose conversion_type_params were dropped during deserialization (missing base_metric/conversion_metric fields) or mutated by config overrides before resolution.
Common situations: A conversion metric YAML missing required nested fields (window, base_metric, conversion_metric); schema changes in MetricTypeParams making the is_none guard stale.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- ModelPropertiesEntry guaranteed to exist for model
- Schema not found for canonical FQN: {}
- `EnterGuard` values dropped out of order. Guards returned by
- {e} {:?}
- {e}
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/4284ab9a15300ece.
Report an issue: GitHub.