dbt-labs/dbt-core · error

group_by with non-string key_type

Error message

group_by with non-string key_type

What it means

dbt-agate's Rust Table group_by only accepts a key_type given as a crate::DataType object reference; any other value (e.g. a raw type name string or a foreign class instance) hits unimplemented!(). Supporting arbitrary DataType class instances is a known TODO in the source.

Source

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

                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,
                };
                let table_set = self
                    .as_ref()
                    .group_by_key(key, key_name, key_type)
                    .map_err(|e| {
                        Error::new(ErrorKind::InvalidOperation, format!("Table.group_by: {e}"))
                    })?;
                Ok(Value::from_object(table_set))
            }
            // ```python
            // def join(self, right_table, left_key=None, right_key=None, inner=False,
            //         full_outer=False, require_match=False, columns=None):
            //     """
            //     Create a new table by joining two table's on common values. This method
            //     implements most varieties of SQL join, in addition to some unique features.

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Construct a crate::DataType instance and pass that as key_type
  2. Omit key_type so it defaults to None
  3. Convert the desired type into crate::DataType before calling group_by

Example fix

// before
let key_type = Value::from("Number");
table.call_method("group_by", kwargs!{"key_type" => key_type})
// after
let key_type = Value::from_object(crate::DataType::number());
table.call_method("group_by", kwargs!{"key_type" => key_type})
Defensive patterns

Strategy: type-guard

Validate before calling

let key_type_ok = key_type.as_ref().and_then(|v| v.downcast_object_ref::<crate::DataType>()).is_some();

Type guard

fn is_data_type(v: &Value) -> bool { v.downcast_object_ref::<crate::DataType>().is_some() }

Prevention

When it happens

Trigger: Calling table.group_by(...) with key_type set to something that does not downcast to crate::DataType, such as a Python-style type object or a string like "Number".

Common situations: Porting Python agate calls like group_by(key, key_type=agate.Number) where the type is passed as a class reference; passing dtype names as strings from config-driven pipelines.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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