{"record":{"id":"71df695f87ed75a2","repo":"dbt-labs/dbt-core","slug":"distinct-with-non-string-keys","errorCode":null,"errorMessage":"distinct with non-string keys","messagePattern":"distinct with non-string keys","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-agate/src/table.rs","lineNumber":1375,"sourceCode":"            //     :returns:\n            //     A new :class:`.Table`.\n            //     \"\"\"\n            // ```\n            \"distinct\" => {\n                let iter = ArgsIter::new(\"Table.distinct\", &[], args);\n                let key = iter.next_kwarg::<Option<&Value>>(\"key\")?;\n                iter.finish()?;\n\n                let key = match key {\n                    Some(v) => {\n                        if let Some(s) = v.as_str() {\n                            Some(vec![s.to_string()])\n                        } else if let Ok(iter) = v.try_iter() {\n                            let mut keys = Vec::new();\n                            for key in iter {\n                                match key.as_str() {\n                                    Some(s) => keys.push(s.to_string()),\n                                    None => unimplemented!(\"distinct with non-string keys\"),\n                                }\n                            }\n                            Some(keys)\n                        } else {\n                            None\n                        }\n                    }\n                    None => None,\n                };\n\n                let result = self.as_ref().distinct(key).map_err(|e| {\n                    Error::new(ErrorKind::InvalidOperation, format!(\"Table.distinct: {e}\"))\n                })?;\n                Ok(Value::from_object(result))\n            }\n            other => unimplemented!(\"AgateTable::{}\", other),\n        }\n    }","sourceCodeStart":1357,"sourceCodeEnd":1393,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-agate/src/table.rs#L1357-L1393","documentation":"dbt-agate's Rust Table.distinct() accepts a keys iterable but only supports string key names; iterating the argument and encountering a non-string Value triggers unimplemented!(). Non-string column identifiers are not implemented.","triggerScenarios":"Calling table.distinct(keys=[...]) where the keys iterable contains a non-string Value (e.g. an integer column index or a column object) mixed with or instead of strings.","commonSituations":"Porting Python agate code that used column indices; dynamically building the keys list from non-string sources; passing a single non-string key wrapped in an iterable.","solutions":["Ensure every element of the keys iterable is a string column name","Convert non-string keys (indices/objects) to column-name strings before the call","Call distinct() with no keys to deduplicate on all columns"],"exampleFix":"// before\ntable.call_method(\"distinct\", kwargs!{\"keys\" => Value::from(vec![Value::from(0)])})\n// after\ntable.call_method(\"distinct\", kwargs!{\"keys\" => Value::from(vec![Value::from(\"id\")])})","handlingStrategy":"validation","validationCode":"let all_strings = keys.iter().all(|k| k.as_str().is_some());\nif !all_strings { panic!(\"distinct keys must all be strings\"); }","typeGuard":"fn all_str_keys(iter: impl Iterator<Item = Value>) -> bool { iter.all(|k| k.as_str().is_some()) }","tryCatchPattern":null,"preventionTips":["Normalize column identifiers to strings before building the keys list","Avoid passing column indices to distinct","Test distinct calls with representative key lists"],"tags":["unimplemented","distinct","type-mismatch","rust"],"backgroundTag":"unsupported-operation","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}