dbt-labs/dbt-core · error · InvalidArgument
Table.select: key must be a string or an array of strings: {
Error message
Table.select: key must be a string or an array of strings: {v} found instead What it means
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.
Source
Thrown at crates/dbt-agate/src/table.rs:1104
Vec::from([single_key.to_string()])
} else {
let iter = match key.try_iter() {
Ok(iter) => iter,
Err(e) => {
return Err(Error::new(
ErrorKind::InvalidArgument,
format!(
"Table.select: key must be a string or an array of strings: {e}"
),
));
}
};
let mut keys = Vec::new();
for v in iter {
if let Some(s) = v.as_str() {
keys.push(s.to_string());
} else {
return Err(Error::new(
ErrorKind::InvalidArgument,
format!(
"Table.select: key must be a string or an array of strings: {v} found instead"
),
));
}
}
keys
};
let table = self.select(keys.as_slice());
Ok(Value::from_object(table))
}
"rename" => {
// def rename(column_names=None, row_names=None,
// slug_columns=False, slug_rows=False,
// **kwargs)
//
// column_names: array | dict | NoneView on GitHub (pinned to 0267ce9170)
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
Example fix
// before table.select(['name', 2]) // after table.select(['name', 'age'])
Defensive patterns
Strategy: type-guard
Validate before calling
def ensure_str_list(keys):
assert all(isinstance(k, str) for k in keys), f'non-string key: {keys}'
return keys Type guard
def is_str_list(v):
return isinstance(v, (list, tuple)) and all(isinstance(k, str) for k in v) Try / catch
try:
result = table.select(keys)
except Exception as e:
if 'found instead' in str(e):
result = table.select([str(k) for k in keys])
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: Dynamically constructed column lists that mix names and indices; deserialized JSON where column selectors were numbers; refactored code passing column positions instead of names.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Table.select: key must be a string or an array of strings: {
- Table.join: right_table must be a Table: {right_table} found
- Table.rename: column_names array must contain only strings,
- Table.rename: row_names array must contain only strings, fou
- A join can not be both "inner" and "full_outer".
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/ff2ce95554905706.
Report an issue: GitHub.