dbt-labs/dbt-core · warning
Detected columns with numeric type and unspecified…
Error message
Detected columns with numeric type and unspecified precision/scale, this can lead to unintended rounding: {col_naked_numeric}` What it means
This warning is emitted when a model column resolves to a numeric (NUMERIC/DECIMAL) type without an explicit precision and scale. Without precision/scale, the database applies its default, which can silently round or truncate values. dbt raises it during get-empty-relation / get_column_schema_from_query work when casting columns via cast().
Solutions
- Add explicit precision and scale to the column type, e.g. cast the column to numeric(38, 9) instead of numeric.
- If using model contracts, set the data_type in the contract's columns block to numeric(p, s).
- If the database's default numeric behavior is acceptable, acknowledge the warning and move on — it is non-fatal.
Example fix
// before
{{ cast('null', 'numeric') }} as my_col
// after
{{ cast('null', 'numeric(38, 9)') }} as my_col Defensive patterns
Strategy: validation
Validate before calling
# dbt schema.yml / model contract check before running
models:
- name: my_model
columns:
- name: my_col
data_type: numeric(38, 9) # specify precision & scale, not bare 'numeric' Prevention
- Always write numeric column types as numeric(p, s) in contracts and casts.
- Add a pre-commit lint that flags bare numeric/decimal in dbt YAML files.
- Verify inferred types by inspecting the built relation after first run.
When it happens
Trigger: A column's data_type is a bare numeric type (e.g. 'numeric', 'decimal') with no '(p,s)' specifier while dbt builds the empty relation or derives a schema from a query; the column passes the col_err check but lands in col_naked_numeric.
Common situations: Inferencing schemas fromCTAS/scratch relations where types come back as unadorned 'numeric'; writing user-defined column types in a model contract without precision; adapters whose default numeric precision differs from what the user expects.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Configuration changes were identified and…
- Found ` ` volatility specified on function ` `. This…
- In relation : The following columns are specified in the…
- order_by_clause is not supported for listagg on…
- Volatility is not supported by
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/0a85a5fe9f255df0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/dbt-loader/src/dbt_macro_assets/dbt-adapters/macros/adapters/columns.sql:77
{%- set col_err = [] -%}
{%- set col_naked_numeric = [] -%}
select
{% for i in columns %}
{%- set col = columns[i] -%}
{%- if col['data_type'] is not defined -%}
{%- do col_err.append(col['name']) -%}
{#-- If this column's type is just 'numeric' then it is missing precision/scale, raise a warning --#}
{#-- TYPE CHECK: col['data_type'] is optional[string] but user have this constraint --#}
{%- elif col['data_type'].strip().lower() in ('numeric', 'decimal', 'number') -%}
{%- do col_naked_numeric.append(col['name']) -%}
{%- endif -%}
{% set col_name = adapter.quote(col['name']) if col.get('quote') else col['name'] %}
{{ cast('null', col['data_type']) }} as {{ col_name }}{{ ", " if not loop.last }}
{%- endfor -%}
{%- if (col_err | length) > 0 -%}
{{ exceptions.column_type_missing(column_names=col_err) }}
{%- elif (col_naked_numeric | length) > 0 -%}
{{ exceptions.warn("Detected columns with numeric type and unspecified precision/scale, this can lead to unintended rounding: " ~ col_naked_numeric ~ "`") }}
{%- endif -%}
{% endmacro %}
-- funcsign: (string, optional[string]) -> list[base_column]
{% macro get_column_schema_from_query(select_sql, select_sql_header=none) -%}
{% set columns = [] %}
{# -- Using an 'empty subquery' here to get the same schema as the given select_sql statement, without necessitating a data scan.#}
{% set sql = get_empty_subquery_sql(select_sql, select_sql_header) %}
{% set column_schema = adapter.get_column_schema_from_query(sql) %}
{{ return(column_schema) }}
{% endmacro %}
-- here for back compat
-- funcsign: (string) -> list[string]
{% macro get_columns_in_query(select_sql) -%}
{{ return(adapter.dispatch('get_columns_in_query', 'dbt')(select_sql)) }}
{% endmacro %}
View on GitHub (pinned to 0267ce9170)