dbt-labs/dbt-core · warning
Both zorder and liquid_clustering are set but they are…
Error message
Both zorder and liquid_clustering are set but they are incompatible. zorder will be ignored.
What it means
Delta tables support either ZORDER optimization or liquid clustering, but not both. In `get_optimize_sql`, if the model config sets both `zorder` and (`liquid_clustered_by` or `auto_liquid_cluster`), dbt warns that zorder will be ignored and emits `optimize` without a zorder clause.
Solutions
- Remove the `zorder` config from the model since liquid clustering takes precedence
- Or remove `liquid_clustered_by`/`auto_liquid_cluster` if you intend to keep ZORDER
- Centralize clustering config in one place (e.g. a shared macro) so both keys can't be set simultaneously
Example fix
# before
{{ config(materialized='incremental', zorder=['user_id'], liquid_clustered_by=['user_id']) }}
# after
{{ config(materialized='incremental', liquid_clustered_by=['user_id']) }} Defensive patterns
Strategy: validation
Validate before calling
def check_clustering_conflict(model):
cfg = model.get('config', {})
if cfg.get('zorder') and (cfg.get('liquid_clustered_by') or cfg.get('auto_liquid_cluster')):
raise ValueError(f"{model['name']}: set both zorder and liquid clustering; zorder will be ignored") Prevention
- Pick one clustering strategy per model — zorder OR liquid clustering
- Provide team defaults via a shared macro that errors on both keys
- Audit models for legacy `zorder` when enabling auto liquid clustering
- Watch for this warning in logs after clustering migrations
When it happens
Trigger: A Delta model sets `config.zorder` AND (`config.liquid_clustered_by` or `config.auto_liquid_cluster`); the `optimize` operation runs (post-hook/on incremental optimize).
Common situations: Enabling auto liquid clustering on an existing table that still carries a legacy `zorder` config; team-wide config defaults adding liquid clustering while individual models set zorder; switching clustering strategy without cleaning up the old key.
Related errors
- Configuration changes were identified and…
- Configuration changes were identified and…
- Constraint of type } with no `name` provided. Generating…
- Constraint of type with no `name` provided. Generating hash…
- Constraints not supported for file format
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/f5dbed99ecb118fc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/dbt-loader/src/dbt_macro_assets/dbt-databricks/macros/relations/optimize.sql:22
{%- macro databricks__optimize(relation) -%}
{%- if config.get('skip_optimize', false) | as_bool -%}
{%- elif var('DATABRICKS_SKIP_OPTIMIZE', 'false')|lower != 'true' and
var('databricks_skip_optimize', 'false')|lower != 'true' and
adapter.resolve_file_format(config) == 'delta' -%}
{%- if (config.get('zorder', False) or config.get('liquid_clustered_by', False)) or config.get('auto_liquid_cluster', False) -%}
{%- call statement('run_optimize_stmt') -%}
{{ get_optimize_sql(relation) }}
{%- endcall -%}
{%- endif -%}
{%- endif -%}
{%- endmacro -%}
{%- macro get_optimize_sql(relation) %}
optimize {{ relation.render() }}
{%- if config.get('zorder', False) and adapter.resolve_file_format(config) == 'delta' %}
{%- if config.get('liquid_clustered_by', False) or config.get('auto_liquid_cluster', False) %}
{{ exceptions.warn("Both zorder and liquid_clustering are set but they are incompatible. zorder will be ignored.") }}
{%- else %}
{%- set zorder = config.get('zorder', none) %}
{# TODO: predicates here? WHERE ... #}
{%- if zorder is sequence and zorder is not string %}
zorder by (
{%- for col in zorder %}
{{ col }}{% if not loop.last %}, {% endif %}
{%- endfor %}
)
{%- else %}
zorder by ({{zorder}})
{%- endif %}
{%- endif %}
{%- endif %}
{%- endmacro -%}
View on GitHub (pinned to 0267ce9170)