dbt-labs/dbt-core · error · minijinja::Error

version must be a string, integer, or float

Error message

version must be a string, integer, or float

What it means

The final fallback arm of NodeVersion's TryFrom<Value> in crates/dbt-schemas/src/schemas/serde.rs. NodeVersion only supports string, integer, and float representations; any other minijinja Value kind (bool, array, dict, undefined, none) passed to the conversion produces this 'version must be a string, integer, or float' error.

Source

Thrown at crates/dbt-schemas/src/schemas/serde.rs:778

                    .expect("kind is String but as_str returned None")
                    .to_owned(),
            )),
            ValueKind::Number => {
                if value.is_integer() {
                    if let Some(i) = value.as_i64() {
                        return Ok(NodeVersion::Integer(i));
                    }
                }
                if let Ok(f) = f64::try_from(value) {
                    Ok(NodeVersion::Float(f))
                } else {
                    Err(minijinja::Error::new(
                        minijinja::ErrorKind::InvalidOperation,
                        "unsupported numeric type for version",
                    ))
                }
            }
            _ => Err(minijinja::Error::new(
                minijinja::ErrorKind::InvalidOperation,
                "version must be a string, integer, or float",
            )),
        }
    }
}

#[derive(Debug, Serialize, UntaggedEnumDeserialize, Clone, PartialEq, Eq, DbtSchema)]
#[serde(untagged)]
pub enum StringOrMap {
    StringValue(String),
    MapValue(HashMap<String, YmlValue>),
}

#[derive(Serialize, UntaggedEnumDeserialize, Debug, Clone, DbtSchema)]
#[serde(untagged)]
pub enum StringOrArrayOfStrings {
    String(String),

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Set version to a scalar: a quoted/unquoted string, integer, or float, e.g. `version: '2.0'` or `version: 2`
  2. Check for empty (`version:` with no value) or list-valued version entries in your YAML
  3. Fix template expressions so they return a defined string/number instead of undefined or a dict
  4. Validate your dbt config schema before running to catch non-scalar version values early

Example fix

# before
version:
  - 1
  - 0
# after
version: '1.0'
Defensive patterns

Strategy: type-guard

Validate before calling

def is_scalar_version(v):
    if isinstance(v, bool) or v is None:
        return False
    return isinstance(v, (str, int, float)) or v is not None and isinstance(v, str)
# simpler: accept only str/int/float, reject bool/None/list/dict

def is_valid_version(v):
    if isinstance(v, bool) or v is None or isinstance(v, (list, dict)):
        return False
    return isinstance(v, (str, int, float))

Type guard

def is_valid_node_version(v):
    return (
        isinstance(v, str)
        or (isinstance(v, (int, float)) and not isinstance(v, bool))
    )

Try / catch

try:
    node_version = NodeVersion.try_from(value)
except Exception:
    raise ValueError(
        f"version must be a string, integer, or float; got {type(value).__name__}: {value!r}"
    )

Prevention

When it happens

Trigger: Assigning a non-scalar value to a `version` field — e.g. `version: [1, 2]`, a dictionary, a boolean, or an undefined/none template result — then converting the Value into NodeVersion via try_from.

Common situations: YAML config where `version:` is left empty (none) or is a list; template logic returning undefined instead of a version string; accidentally nesting version under the wrong key so a collection is passed.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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