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.

Solutions

  1. Ensure every element of the key list is a string column name
  2. Convert indices to names: `[table.column_names[i] for i in indices]`
  3. Filter or cast the list: `[str(k) for k in keys]` before calling select
  4. 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

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


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

Appendix: 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 | None

View on GitHub (pinned to 0267ce9170)