dbt-labs/dbt-core · error

Table.rename: row_names array must contain only strings, fou

Error message

Table.rename: row_names array must contain only strings, found: {}

What it means

When row_names is given as an array to Table.rename, each element must be a string replacing the row's name positionally. A non-string element was encountered at some row index and the error reports the offending value.

Source

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

                    let iter = match v.try_iter() {
                        Ok(iter) => iter,
                        Err(_) => {
                            return Err(Error::new(
                                ErrorKind::InvalidArgument,
                                "Table.rename: row_names must be a map or an array",
                            ));
                        }
                    };

                    // Collect the iterator values
                    let values: Vec<_> = iter.collect();

                    for i in 0..self.num_rows() {
                        if let Some(value) = values.get(i) {
                            if let Some(s) = value.as_str() {
                                renamed.append_value(s);
                            } else {
                                return Err(Error::new(
                                    ErrorKind::InvalidArgument,
                                    format!(
                                        "Table.rename: row_names array must contain only strings, found: {}",
                                        value
                                    ),
                                ));
                            }
                        } else {
                            renamed.append_option(old_row_name(i));
                        }
                    }
                    Ok(Arc::new(renamed.finish()))
                }
            })
            .transpose()?;

        self.rename(renamed_columns, renamed_rows, slug_columns, slug_rows)
    }

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Stringify every element of the row_names array before calling rename.
  2. Only pass arrays whose elements are confirmed strings.
  3. Use the map form of row_names if you only need to rename specific rows.

Example fix

// before
rename(None, Some(vec![0, 1, 2]), false, false)
// after
rename(None, Some(vec!["0", "1", "2"]), false, false)
Defensive patterns

Strategy: type-guard

Validate before calling

let all_strings = row_names.iter().all(|v| v.as_str().is_some());
if !all_strings { panic!("row_names must contain only strings"); }

Type guard

fn all_row_strings(v: &[Value]) -> bool {
    v.iter().all(|x| x.as_str().is_some())
}

Try / catch

match result {
    Err(e) if e.to_string().contains("row_names array must contain only strings") => {
        let coerced: Vec<String> = raw_rows.iter().map(|v| v.to_string()).collect();
        table.rename(None, Some(coerced), false, false)?
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling table.rename with a row_names array containing integers, floats, nulls or nested values, e.g. [0, 1, 2].

Common situations: Auto-generating row names from numeric row indices without stringifying; loading row labels from a numeric column; JSON arrays where numbers were not quoted.

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/517b3094656b5e52. Report an issue: GitHub.