dbt-labs/dbt-core · warning
In relation : The following columns are specified in the…
Error message
In relation {relation.render()}: The following columns are specified in the schema but are not present in the database: {missing | join(", ")} What it means
During persist_docs, dbt compares the columns declared in the model's schema (YAML/docs config) against the columns actually present in the materialized relation. Columns declared in the schema but missing from the database are collected into `missing` and reported via this warning so users know their docs/config reference columns that don't exist.
Solutions
- Update the model's YAML docs/columns block so it only lists columns that exist in the built relation.
- Rebuild/run the model so the relation matches the declared schema, then re-run `dbt docs generate` or persist_docs.
- Check for case-sensitivity or quoting mismatches between the schema column names and the database column names.
Example fix
// before (schema.yml) columns: - name: old_col // after columns: - name: new_col
Defensive patterns
Strategy: validation
Validate before calling
# Compare declared docs columns against the relation before persisting docs
# dbt: run `dbt compile && dbt run-operation get_columns_specified_in --args ...`
# or in Python after a run:
# relation_columns = {c.name for c in adapter.get_columns(relation)}
# yaml_columns = set(model['columns'].keys())
# assert yaml_columns <= relation_columns, f"missing: {yaml_columns - relation_columns}" Prevention
- Regenerate the YAML docs block from the actual relation columns whenever the model SQL changes.
- Use dbt-codegen to produce the schema.yml instead of hand-writing column lists.
- Watch for case mismatches between YAML names and database column names.
When it happens
Trigger: Calling default__persist_docs (or get_columns_specified_in but not in the database) where iterating the model's column specs finds a name that has no entry in the database relation's column list, appending it to `missing`.
Common situations: YAML docs blocks list a column that was renamed or dropped in the model SQL; case-sensitivity mismatch between the schema file and the database; persist_docs enabled on an external/view relation whose columns drifted from the declared schema.
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
- Configuration changes were identified and…
- Detected columns with numeric type and unspecified…
- Found ` ` volatility specified on function ` `. This…
- Volatility is not supported by
- Argument must be a string
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/4e4684cbdc634130.
Report an issue: GitHub.
Appendix: source
Thrown at crates/dbt-loader/src/dbt_macro_assets/dbt-adapters/macros/adapters/persist_docs.sql:51
{% macro validate_doc_columns(relation, column_dict, existing_column_names, case_insensitive=false) %}
{% set existing_lower = existing_column_names | map("lower") | list %}
{% set missing = [] %}
{% set filtered = {} %}
{% for col_name in column_dict %}
{% set is_quoted = column_dict[col_name]['quote'] %}
{% if case_insensitive or not is_quoted %}
{% set present = col_name | lower in existing_lower %}
{% else %}
{% set present = col_name in existing_column_names %}
{% endif %}
{% if present %}
{% do filtered.update({col_name: column_dict[col_name]}) %}
{% else %}
{% do missing.append(col_name) %}
{% endif %}
{% endfor %}
{% if missing | length > 0 %}
{{ exceptions.warn("In relation " ~ relation.render() ~ ": The following columns are specified in the schema but are not present in the database: " ~ missing | join(", ")) }}
{% endif %}
{{ return(filtered) }}
{% endmacro %}
-- funcsign: (relation, model, optional[bool], optional[bool]) -> string
{% macro default__persist_docs(relation, model, for_relation, for_columns) -%}
{% if for_relation and config.persist_relation_docs() and model.description %}
{% do run_query(alter_relation_comment(relation, model.description)) %}
{% endif %}
{% if for_columns and config.persist_column_docs() and model.columns %}
{% set existing_columns = adapter.get_columns_in_relation(relation) | map(attribute="name") | list %}
{% set filtered_columns = validate_doc_columns(relation, model.columns, existing_columns) %}
{% set alter_comment_sql = alter_column_comment(relation, filtered_columns) %}
{% if alter_comment_sql and alter_comment_sql | trim | length > 0 %}
{% do run_query(alter_comment_sql) %}
{% endif %}
{% endif %}View on GitHub (pinned to 0267ce9170)