dbt-labs/dbt-core · warning
Invalid constraint for column
Error message
Invalid constraint for column {{ column_name }}. Only `not_null` is supported. What it means
This warning is emitted by the Spark adapter's `spark__alter_column_set_constraints` macro when applying column-level constraints. Spark SQL only supports setting `not null` via `ALTER TABLE ... CHANGE COLUMN ... SET NOT NULL`; any other constraint type (unique, primary key, check, etc.) is skipped and a warning is raised. The model still runs, but the unsupported constraint is silently not enforced.
Solutions
- Remove non-`not_null` constraints from the column definition in schema.yml or the model config for Spark models
- Keep only `not_null` constraints, which the macro translates to `ALTER TABLE ... SET NOT NULL`
- Enforce other constraints at the warehouse/engine level manually (e.g. via post-hook DDL) if the Spark distribution supports them
- Wrap constraints in a `contract` with enforced=false so dbt documents them without attempting DDL
Example fix
// before (schema.yml)
columns:
- name: id
constraints:
- type: not_null
- type: unique
// after
columns:
- name: id
constraints:
- type: not_null Defensive patterns
Strategy: validation
Validate before calling
// before running, lint schema.yml constraints for Spark targets
function hasUnsupportedConstraints(constraints) {
return (constraints || []).filter(c => c.type !== 'not_null');
}
const unsupported = hasUnsupportedConstraints(column.constraints);
if (unsupported.length) console.warn('Spark only supports not_null; remove:', unsupported.map(c => c.type)); Prevention
- Only declare not_null constraints on Spark models
- Move unique/PK declarations into dbt tests (unique, relationships) instead of column constraints
- Review constraints when porting models from Postgres/BigQuery to Spark
- Use contracts with enforced=false for documentation-only constraints
When it happens
Trigger: Defining model-level/column-level `constraints` in a dbt-spark model config with any `type` other than `not_null`, then running the model so the alter-constraints step executes.
Common situations: Porting models from Postgres/BigQuery where unique or primary key constraints are declared in schema.yml; teams assuming dbt contract constraints are enforced on Spark.
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
- order_by_clause is not supported for listagg on…
- Constraint of type } with no `name` provided. Generating…
- Constraint of type with no `name` provided. Generating hash…
- Constraints not supported for file format
- Invalid primary key column
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/b67c4a728aa1e44f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/dbt-loader/src/dbt_macro_assets/dbt-spark/macros/adapters.sql:231
{% if constraint.type == 'check' and not is_incremental() %}
{%- set constraint_hash = local_md5(column_name ~ ";" ~ constraint.expression ~ ";" ~ loop.index) -%}
{% call statement() %}
alter table {{ relation }} add constraint {{ constraint.name if constraint.name else constraint_hash }} check ({{ constraint.expression }});
{% endcall %}
{% endif %}
{% endfor %}
{% endmacro %}
{% macro alter_column_set_constraints(relation, column_dict) %}
{{ return(adapter.dispatch('alter_column_set_constraints', 'dbt')(relation, column_dict)) }}
{% endmacro %}
{% macro spark__alter_column_set_constraints(relation, column_dict) %}
{% for column_name in column_dict %}
{% set constraints = column_dict[column_name]['constraints'] %}
{% for constraint in constraints %}
{% if constraint.type != 'not_null' %}
{{ exceptions.warn('Invalid constraint for column ' ~ column_name ~ '. Only `not_null` is supported.') }}
{% else %}
{% set quoted_name = adapter.quote(column_name) if column_dict[column_name]['quote'] else column_name %}
{% call statement() %}
alter table {{ relation }} change column {{ quoted_name }} set not null {{ constraint.expression or "" }};
{% endcall %}
{% endif %}
{% endfor %}
{% endfor %}
{% endmacro %}
{% macro get_column_comment_sql(column_name, column_dict) -%}
{% if column_name in column_dict and column_dict[column_name]["description"] -%}
{% set escaped_description = column_dict[column_name]["description"] | replace("'", "\\'") %}
{% set column_comment_clause = "comment '" ~ escaped_description ~ "'" %}
{%- endif -%}
{{ adapter.quote(column_name) }} {{ column_comment_clause }}
{% endmacro %}
View on GitHub (pinned to 0267ce9170)