dbt-labs/dbt-core · error · minijinja::Error (InvalidOperation)

argument 'name' to has_var() has incompatible type; value is

Error message

argument 'name' to has_var() has incompatible type; value is not a string

What it means

Type guard in DbtJinjaVars::call_has_var: the first positional argument to has_var() must be a variable name, but the supplied Jinja value is not a string, so it cannot name a var to look up. The at-fault input is the argument passed to has_var() in the template.

Source

Thrown at crates/dbt-jinja-vars/src/var.rs:121

            format!(
                "Required var '{}' not found in config:\nVars supplied to {} = {}",
                var_name,
                package_name,
                serde_json::to_string_pretty(vars_lookup).unwrap()
            ),
        )
    }

    /// Common handler for `has_var`.
    fn call_has_var(&self, state: &State<'_, '_>, args: &[Value]) -> Result<Value, Error> {
        if args.is_empty() {
            return Err(Error::new(
                ErrorKind::InvalidOperation,
                "has_var requires 1 argument",
            ));
        }
        let var_name = args[0].as_str().ok_or_else(|| {
            Error::new(
                ErrorKind::InvalidOperation,
                "argument 'name' to has_var() has incompatible type; value is not a string",
            )
        })?;
        let present = self.contains_var(state, var_name)?;
        Ok(Value::from(present))
    }

    /// Common implementation for `Object::call`.
    fn call_impl(
        self: &Arc<Self>,
        state: &State<'_, '_>,
        args: &[Value],
        _listeners: &[Rc<dyn RenderingEventListener>],
    ) -> Result<Value, Error> {
        let (var_name, default_value) = Self::parse_args(args)?;
        self.call_as_function(state, var_name, default_value)
    }

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Quote the name: `has_var('my_var')`.
  2. Coerce dynamic names with the `| string` filter: `has_var(key | string)`.
  3. Ensure you pass the lookup key, not the value you expect it to hold.

Example fix

// before (Jinja)
{% if has_var(warehouse_id) %}
// after
{% if has_var('warehouse_id') %}
Defensive patterns

Strategy: type-guard

Validate before calling

{% if candidate is not string %}{{ exceptions.raise_compiler_error('has_var name must be a string') }}{% endif %}

Type guard

// Jinja
{% macro safe_has_var(name) %}
  {% if name is not string %}{{ return(false) }}{% endif %}
  {{ return(has_var(name | string)) }}
{% endmacro %}

Prevention

When it happens

Trigger: Calling `{{ has_var(42) }}`, `{{ has_var(some_var_value) }}` where the value is not a string, or passing a dict/list of candidate names.

Common situations: Passing the var's value instead of its name (confusing `has_var(my_var)` with checking the value); numeric column names used as var keys; dynamically built names not coerced to strings.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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