dbt-labs/dbt-core · error · InvalidOperation

set_strict requires an iterable value

Error message

set_strict requires an iterable value

What it means

set_strict() calls try_iter() on its single argument and throws this InvalidOperation error when the value is not iterable (e.g. a string is technically iterable in some engines, but numbers, booleans, dicts-as-scalars, or none are not usable here). The 'strict' contract is to fail rather than silently coerce.

Solutions

  1. Ensure the argument is a list/sequence: set_strict([1,2,3])
  2. Coerce scalars into a one-element list: set_strict([value])
  3. Use var('x', []) with a list default, or validate with `x is iterable` / sequence test before calling

Example fix

// before
{% set s = set_strict(var('ids')) %}
// after
{% set ids = var('ids', []) %}
{% set s = set_strict(ids if ids is sequence else [ids]) %}
Defensive patterns

Strategy: validation

Validate before calling

{% if ids is not sequence %}
  {% set ids = [ids] %}
{% endif %}
{% set s = set_strict(ids) %}

Type guard

{% macro as_list(x) %}{{ return(x if x is sequence else [x]) }}{% endmacro %}

Prevention

When it happens

Trigger: Calling set_strict(5), set_strict(none), set_strict(my_dict) where my_dict iteration is not supported, or set_strict(undefined_var) where the variable never got assigned a list.

Common situations: A config or var expected to be a list but supplied as a scalar (var('x') default being a string/number); a Jinja expression returning none due to a failed lookup upstream; refactors changing a variable from list to scalar.

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/1826f7ede433ef75. Report an issue: GitHub.

Appendix: source

Thrown at crates/dbt-jinja-utils/src/functions/base.rs:779

/// {% set unique_values = set_strict(my_list) %}
/// -- Returns [1, 2, 3] or fails if my_list is not iterable
/// ```
pub fn set_strict_fn() -> impl Fn(&[Value], Kwargs) -> Result<Value, Error> {
    move |args: &[Value], _kwargs: Kwargs| -> Result<Value, Error> {
        if args.len() != 1 {
            return Err(Error::new(
                ErrorKind::InvalidOperation,
                "set_strict requires exactly 1 argument",
            ));
        }

        let value = &args[0];
        match value.try_iter() {
            Ok(iter) => {
                let set: BTreeSet<_> = iter.map(|v| v.to_string()).collect();
                Ok(Value::from_iter(set))
            }
            Err(_) => Err(Error::new(
                ErrorKind::InvalidOperation,
                "set_strict requires an iterable value",
            )),
        }
    }
}

/// Try to call a function and raise a CompilationError if it raises an exception.
///
/// Args:
///     message_if_exception: The message to raise if the function raises an exception
///     func: The function to call
///     *args: The arguments to pass to the function
///     **kwargs: The keyword arguments to pass to the function
///
/// Example:
/// ```jinja
/// {% set result = try_or_compiler_error("Error", my_function, arg1, arg2, kwarg1="value1", kwarg2="value2") %}

View on GitHub (pinned to 0267ce9170)