dbt-labs/dbt-core · error

Table.rename: column_names must be a map or an array

Error message

Table.rename: column_names must be a map or an array

What it means

Table.rename was called with a column_names argument that is neither a map (old-name -> new-name) nor an array of new column names. The library attempts to interpret the value as a generic iterable when it is not a map, and throws this error if the value cannot be iterated at all. This mirrors agate's Python rename(), which accepts only mappings or sequences for column_names.

Source

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

                                if key.as_str().is_some_and(|k| k == col) {
                                    renamed[i] = value.to_string();
                                }
                            }
                        }
                        renamed
                    }};
                }
                if let Some(map) = v.downcast_object_ref::<ValueMap>() {
                    Ok(rename_columns_by_map!(map))
                } else if let Some(map) = v.downcast_object_ref::<MutableMap>() {
                    let map: ValueMap = map.clone().into();
                    Ok(rename_columns_by_map!(map))
                } else {
                    // Try to treat it as a generic iterable
                    let iter = match v.try_iter() {
                        Ok(iter) => iter,
                        Err(_) => {
                            return Err(Error::new(
                                ErrorKind::InvalidArgument,
                                "Table.rename: column_names must be a map or an array",
                            ));
                        }
                    };
                    let mut renamed = old;
                    for (i, value) in iter.enumerate() {
                        if i >= renamed.len() {
                            break;
                        }
                        if let Some(s) = value.as_str() {
                            renamed[i] = s.to_string();
                        } else {
                            return Err(Error::new(
                                ErrorKind::InvalidArgument,
                                format!(
                                    "Table.rename: column_names array must contain only strings, found: {}",
                                    value

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Pass column_names as a map of old column name to new column name, e.g. {"old": "new"}.
  2. Pass column_names as a plain array of new column name strings, one per column.
  3. Omit column_names entirely if you only intend to rename rows.

Example fix

// before
table.rename("new_name", None, false, false)
// after
table.rename(Some(vec!["new_name"]), None, false, false)
Defensive patterns

Strategy: validation

Validate before calling

fn valid_column_names(v: &Value) -> bool {
    v.as_map().is_some()
        || v.as_array().map_or(false, |a| a.iter().all(|x| x.as_str().is_some()))
}

Type guard

fn is_name_spec(v: &Value) -> bool {
    v.as_map().is_some()
        || v.as_array().map_or(false, |a| a.iter().all(|x| x.as_str().is_some()))
}

Try / catch

match table.rename(column_names, row_names, false, false) {
    Ok(t) => t,
    Err(e) if e.to_string().contains("column_names must be a map or an array") => {
        eprintln!("column_names must be a map or array of strings: {e}");
        table.rename(default_names, None, false, false)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling table.rename with column_names set to a scalar (e.g. a string instead of an array of strings), an integer, a struct without iteration support, or a non-iterable value instead of a map/array.

Common situations: Passing a single string like "col_a" instead of ["col_a", "col_b"]; passing a hash-map-like object that the bridge cannot convert; porting Python agate code where column_names was a dict and the Rust binding expects a map or array.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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