{"record":{"id":"ff2ce95554905706","repo":"dbt-labs/dbt-core","slug":"table-select-key-must-be-a-string-or-an-array-of-ff2ce9","errorCode":null,"errorMessage":"Table.select: key must be a string or an array of strings: {v} found instead","messagePattern":"Table\\.select: key must be a string or an array of strings: (.+?) found instead","errorType":"validation","errorClass":"InvalidArgument","httpStatus":null,"severity":"error","filePath":"crates/dbt-agate/src/table.rs","lineNumber":1104,"sourceCode":"                    Vec::from([single_key.to_string()])\n                } else {\n                    let iter = match key.try_iter() {\n                        Ok(iter) => iter,\n                        Err(e) => {\n                            return Err(Error::new(\n                                ErrorKind::InvalidArgument,\n                                format!(\n                                    \"Table.select: key must be a string or an array of strings: {e}\"\n                                ),\n                            ));\n                        }\n                    };\n                    let mut keys = Vec::new();\n                    for v in iter {\n                        if let Some(s) = v.as_str() {\n                            keys.push(s.to_string());\n                        } else {\n                            return Err(Error::new(\n                                ErrorKind::InvalidArgument,\n                                format!(\n                                    \"Table.select: key must be a string or an array of strings: {v} found instead\"\n                                ),\n                            ));\n                        }\n                    }\n                    keys\n                };\n                let table = self.select(keys.as_slice());\n                Ok(Value::from_object(table))\n            }\n            \"rename\" => {\n                //     def rename(column_names=None, row_names=None,\n                //                slug_columns=False, slug_rows=False,\n                //                **kwargs)\n                //\n                //     column_names: array | dict | None","sourceCodeStart":1086,"sourceCodeEnd":1122,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-agate/src/table.rs#L1086-L1122","documentation":"Thrown by `Table.select()` when the `key` argument is an iterable but contains an element that is not a string. Each item of the key array must be a column name string; a non-string element (e.g. a number or nested list) triggers this InvalidArgument error. It complements error 391, which covers keys that are not iterable at all.","triggerScenarios":"Calling `table.select(['col1', 2])` or any list passed as `key` where at least one element fails `v.as_str()` — mixed-type lists, integer column indices, or nested containers.","commonSituations":"Dynamically constructed column lists that mix names and indices; deserialized JSON where column selectors were numbers; refactored code passing column positions instead of names.","solutions":["Ensure every element of the key list is a string column name","Convert indices to names: `[table.column_names[i] for i in indices]`","Filter or cast the list: `[str(k) for k in keys]` before calling select","Validate the list contents with a type check before the call"],"exampleFix":"// before\ntable.select(['name', 2])\n// after\ntable.select(['name', 'age'])","handlingStrategy":"type-guard","validationCode":"def ensure_str_list(keys):\n    assert all(isinstance(k, str) for k in keys), f'non-string key: {keys}'\n    return keys","typeGuard":"def is_str_list(v):\n    return isinstance(v, (list, tuple)) and all(isinstance(k, str) for k in v)","tryCatchPattern":"try:\n    result = table.select(keys)\nexcept Exception as e:\n    if 'found instead' in str(e):\n        result = table.select([str(k) for k in keys])\n    else:\n        raise","preventionTips":["Cast all key elements to str before select","Avoid mixing column indices and names in one list","Validate lists coming from JSON/config before use"],"tags":["rust","type-error","argument-validation"],"backgroundTag":"invalid-argument-value","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"}