dbt-labs/dbt-core · error

group_by with function key

Error message

group_by with function key

What it means

In dbt-agate's table object, group_by accepts a key that may be a string column name or (in upstream agate) a function. The Rust port only resolves string keys; when the key kwarg is not a string (e.g. a callable/function Value), it panics with unimplemented!("group_by with function key") instead of evaluating the function per row.

Source

Thrown at crates/dbt-agate/src/table.rs:1179

            //     :param key_type:
            //         An instance of any subclass of :class:`.DataType`. If not provided
            //         it will default to a :class`.Text`.
            //     :returns:
            //         A :class:`.TableSet` mapping where the keys are unique values from
            //         the :code:`key` and the values are new :class:`.Table` instances
            //         containing the grouped rows.
            //     """
            // ```
            "group_by" => {
                let iter = ArgsIter::new("Table.group_by", &["key"], args);
                let key = iter.next_arg::<&Value>()?;
                let key_name = iter.next_kwarg::<Option<&Value>>("key_name")?;
                let key_type = iter.next_kwarg::<Option<&Value>>("key_type")?;
                iter.finish()?;

                let key = match key.as_str() {
                    Some(s) => s,
                    None => unimplemented!("group_by with function key"),
                };
                let key_name = match key_name {
                    Some(v) => match v.as_str() {
                        Some(s) => s,
                        None => unimplemented!("group_by with non-string key_name"),
                    },
                    None => "group",
                };
                let key_type = match key_type {
                    Some(ty) => match ty.downcast_object_ref::<crate::DataType>() {
                        Some(dt) => Some(dt.clone()),
                        None => {
                            // TODO: support DataType class instances
                            unimplemented!("group_by with non-string key_type")
                        }
                    },
                    None => None,
                };

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Group by an existing string column name instead of a function; pre-compute the derived values into a column first, then group_by that column name.
  2. Add a computed column to the table (table.compute / derive) holding the key expression's results, then call group_by("derived_col").
  3. If function keys are required, extend the Rust group_by to evaluate callable Values per row.

Example fix

// before
table.group_by(lambda_fn, key_name="k")

// after
table = table.compute([[lambda_fn, "k"]])
table.group_by("k", key_name="key_name")
Defensive patterns

Strategy: validation

Validate before calling

{% if key is string %}
  {% set grouped = table.group_by(key) %}
{% else %}
  {% do exceptions.raise_compiler_error("group_by requires a string column key") %}
{% endif %}

Type guard

fn is_string_key(v: &Value) -> bool { v.as_str().is_some() }

Prevention

When it happens

Trigger: Calling table.group_by(key=<function or non-string Value>) from Jinja/Python-interop code — the key kwarg resolves via as_str() to None, hitting the unimplemented!() branch.

Common situations: Porting Python agate code that groups by a lambda/key function into dbt Jinja; macros that compute dynamic group keys with callables; passing a non-string key object (e.g. a computed column expression) to group_by.

Related errors


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