dbt-labs/dbt-core · warning

unenforced constraint type: {constraint.type}

Error message

unenforced constraint type: {constraint.type}

What it means

A warning mirroring error 785 but for foreign_key constraints: when a foreign_key constraint sets `warn_unenforced: true` and the adapter (Databricks) does not enforce foreign keys, the macro warns using `constraint.type` before rendering the ADD CONSTRAINT statement. Databricks foreign keys are declarative only (used by the optimizer for join pruning), not enforced on writes. Compilation continues normally.

Source

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

    {% if not name %}
      {% if local_md5 %}
        {{ exceptions.warn("Constraint of type " ~ type ~ " with no `name` provided. Generating hash instead for relation " ~ relation.identifier) }}
        {%- set hash_input = "primary_key;" ~ relation.identifier ~ ";" ~ column_names ~ ";" -%}
        {%- if pk_expression -%}
          {%- set hash_input = hash_input ~ pk_expression ~ ";" -%}
        {%- endif -%}
        {%- set name = local_md5(hash_input) -%}
      {% else %}
        {{ exceptions.raise_compiler_error("Constraint of type " ~ type ~ " with no `name` provided, and no md5 utility.") }}
      {% endif %}
    {% endif %}
    {% set pk_suffix = (" " ~ pk_expression) if pk_expression else "" %}
    {% set stmt = "alter table " ~ relation.render() ~ " add constraint " ~ name ~ " primary key(" ~ joined_names ~ ")" ~ pk_suffix ~ ";" %}
    {% do statements.append(stmt) %}
  {% elif type == 'foreign_key' %}

    {% if constraint.get('warn_unenforced') %}
      {{ exceptions.warn("unenforced constraint type: " ~ constraint.type)}}
    {% endif %}

    {% set name = constraint.get('name') %}
    
    {% if constraint.get('expression') %}

      {% if not name %}
        {% if local_md5 %}
          {{ exceptions.warn("Constraint of type " ~ type ~ " with no `name` provided. Generating hash instead for relation " ~ relation.identifier) }}
          {%- set name = local_md5("foreign_key;" ~ relation.identifier ~ ";" ~ constraint.get('expression') ~ ";") -%}
        {% 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 ~ " foreign key" ~ constraint.get('expression') %}
    {% else %}
      {% set column_names = constraint.get('columns', []) %}

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Set `warn_unenforced: false` on the foreign_key constraint to silence it once you accept Databricks does not enforce FKs.
  2. Keep the warning while auditing, then disable it project-wide via constraint config defaults.
  3. Enforce referential integrity in-pipeline with dbt tests (relationships test) instead of relying on the DDL constraint.
  4. Remove the foreign_key constraint if declarative-only metadata provides no value for your workload.

Example fix

// before
- type: foreign_key
  to: ref('parent')
  warn_unenforced: true
// after
- type: foreign_key
  to: ref('parent')
  warn_unenforced: false
Defensive patterns

Strategy: validation

Validate before calling

# CI check: no unenforced FK warnings on databricks
# dbt build --select ... 2>&1 | grep 'unenforced constraint type' && exit 1
# or set defaults:
# dbt_project.yml
models:
  +constraints:
    - type: foreign_key
      warn_unenforced: false

Prevention

When it happens

Trigger: A model defines a `foreign_key` constraint with `warn_unenforced: true` (model-level constraints or `contract.enforced`-adjacent configs) on dbt-databricks; the branch at constraints.sql:222-225 fires during compile/run.

Common situations: Migrating FK-enforcing warehouses (Postgres, SQL Server) to Databricks; enabling warn_unenforced to discover which constraints are silently unenforced; inherited configs where warn_unenforced defaults on for foreign keys.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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