dbt-labs/dbt-core · warning

not_null constraint on invalid column: {column_name}

Error message

not_null constraint on invalid column: {column_name}

What it means

A `not_null` constraint was declared for a column name that does not exist in the model's `columns` dictionary (or has no column entry), so dbt cannot build the ALTER TABLE ... SET NOT NULL statement and warns instead of applying it. The constraint is silently unenforced.

Source

Thrown at crates/dbt-loader/src/dbt_macro_assets/dbt-databricks/macros/relations/constraints.sql:180

      {% else %}
        {{ exceptions.raise_compiler_error("Constraint of type " ~ type ~ " with no `name` provided, and no md5 utility.") }}
      {% endif %}
    {% endif %}
    {% set stmt = "alter table " ~ relation.render() ~ " add constraint " ~ name ~ " check (" ~ expression ~ ");" %}
    {% do statements.append(stmt) %}
  {% elif type == 'not_null' %}
    {% set column_names = constraint.get('columns', []) %}
    {% if column and not column_names %}
      {% set column_names = [column['name']] %}
    {% endif %}
    {% for column_name in column_names %}
      {% set column = model.get('columns', {}).get(column_name) %}
      {% if column %}
        {% set quoted_name = adapter.quote(column['name']) %}
        {% set stmt = "alter table " ~ relation.render() ~ " change column " ~ quoted_name ~ " set not null " ~ (constraint.expression or "") ~ ";" %}
        {% do statements.append(stmt) %}
      {% else %}
        {{ exceptions.warn('not_null constraint on invalid column: ' ~ column_name) }}
      {% endif %}
    {% endfor %}
  {% elif type == 'primary_key' %}
    {% if constraint.get('warn_unenforced') %}
      {{ exceptions.warn("unenforced constraint type: " ~ type)}}
    {% endif %}
    {% set column_names = constraint.get('columns', []) %}
    {% if column and not column_names %}
      {% set column_names = [column['name']] %}
    {% endif %}
    {% set quoted_names = [] %}
    {% for column_name in column_names %}
      {% set column = model.get('columns', {}).get(column_name) %}
      {% if not column %}
        {{ exceptions.warn('Invalid primary key column: ' ~ column_name) }}
      {% else %}
        {% set quoted_name = adapter.quote(column['name']) %}
        {% do quoted_names.append(quoted_name) %}

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Fix the column name in the constraint declaration to exactly match a column in the model's columns config.
  2. Remove the constraint if the column no longer exists.
  3. Add the column entry under the model's `columns:` in schema.yml so the constraint resolves.

Example fix

# before (schema.yml, column 'user_id' not in model)
- type: not_null
  columns: [usr_id]
# after
- type: not_null
  columns: [user_id]
Defensive patterns

Strategy: validation

Validate before calling

# Validate constraint columns exist in the model before running:
model_cols = set(model.get('columns', {}).keys())
for c in constraints:
    for col in c.get('columns', []):
        if col not in model_cols:
            raise ValueError(f"not_null constraint references unknown column: {col}")

Prevention

When it happens

Trigger: A model-level or yml constraint referencing a `column_name` that is not present in the model's rendered `model['columns']` mapping — typically a typo, or a constraint declared at model level with no matching column-level definition.

Common situations: Renaming a column without updating the constraint; declaring constraints in schema.yml under a column that doesn't exist in the SELECT list; copy-pasted constraint blocks referencing stale column names.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/15eedbc1795bb483. Report an issue: GitHub.