dbt-labs/dbt-core · error · minijinja::Error::InvalidOperation
parse_constraints: {e}
Error message
parse_constraints: {e} What it means
This error is raised by `typed_constraint::parse_constraints` when a contract-enforced model's column refs and model constraints cannot be parsed into not-null lists and typed constraints. The library wraps the failure as a minijinja InvalidOperation with the message 'parse_constraints: {e}'. It indicates the constraints declared on a contracted model are invalid for the columns they reference.
Source
Thrown at crates/dbt-adapter/src/adapter/adapter_impl.rs:4691
})?;
let model_constraints_vec: Vec<ModelConstraint> =
minijinja_value_to_typed_struct(model_constraints.clone()).map_err(|e| {
minijinja::Error::new(
minijinja::ErrorKind::SerdeDeserializeError,
format!("model_constraints: {e}"),
)
})?;
let column_refs: Vec<DbtColumnRef> = model_columns_map
.values()
.map(|c| Arc::new(c.clone()))
.collect();
let (not_nulls, typed_constraints) = if contract_enforced {
typed_constraint::parse_constraints(&column_refs, &model_constraints_vec).map_err(
|e| {
minijinja::Error::new(
minijinja::ErrorKind::InvalidOperation,
format!("parse_constraints: {e}"),
)
},
)?
} else {
if model_columns_map
.values()
.any(|column| !column.constraints.is_empty())
{
let model_ref = if model_name.is_empty() {
String::new()
} else {
format!(" on '{model_name}'")
};
emit_info_log_message(format!(
"Skipping column-level constraints{model_ref}: set `contract.enforced: true` \
to apply NOT NULL / primary key / foreign key / check constraints."View on GitHub (pinned to 0267ce9170)
Solutions
- Read the inner error text after 'parse_constraints: ' to find the offending constraint/column
- Verify every constraint's column matches a column defined in the model's `columns:` block
- Remove or fix constraints whose type is invalid for the column's data_type (contract validation is strict)
- Disable contract enforcement (`contract.enforced: false`) if contracts are not actually needed while debugging
Example fix
// before
columns:
- name: user_id
constraints:
- type: foreign_key
// after
columns:
- name: user_id
constraints:
- type: foreign_key
expression: other_table (id) Defensive patterns
Strategy: validation
Validate before calling
// before materializing a contracted model
let constraint_columns: HashSet<&str> = model_constraints.iter().filter_map(|c| c.columns.as_ref()).flatten().map(|s| s.as_str()).collect();
let defined: HashSet<&str> = column_refs.iter().map(|c| c.name.as_str()).collect();
let dangling: Vec<_> = constraint_columns.difference(&defined).collect();
if !dangling.is_empty() { return Err(format!("constraints reference unknown columns: {dangling:?}")); } Type guard
fn constraint_columns_exist(constraints: &[ModelConstraint], cols: &[DbtColumnRef]) -> bool {
let names: HashSet<&str> = cols.iter().map(|c| c.name()).collect();
constraints.iter().all(|c| c.referenced_columns().iter().all(|col| names.contains(col.as_str())))
} Try / catch
match typed_constraint::parse_constraints(&column_refs, &model_constraints_vec) {
Ok(r) => r,
Err(e) => return Err(minijinja::Error::new(minijinja::ErrorKind::InvalidOperation,
format!("parse_constraints: {e}; check constraint column references and contract config"))),
} Prevention
- Run dbt compile with contract enforced locally to catch constraint errors early
- Ensure every constraint column exists in the model's columns block
- Rename-dependent constraints should be updated whenever columns are renamed
When it happens
Trigger: Materializing a model with `contract: {enforced: true}` where `parse_constraints(&column_refs, &model_constraints_vec)` fails — e.g. a constraint references a column name not present in column_refs, or a constraint type is incompatible with the declared column data type.
Common situations: Developers hit this when adding model contracts: a constraint names a column that was renamed or removed, a `check` constraint lacks an expression, or a foreign_key constraint references a missing column, all while contract enforcement is on.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- constraint support not implemented
- formula file not found: {}
- formula filename does not end in .rb: {filename}
- --commit-author and --commit-email must be set together
- SemVer build metadata not supported in {semver:?}
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/041daf6462be4214.
Report an issue: GitHub.