dbt-labs/dbt-core · error
Table.join: columns must be a sequence of column names
Error message
Table.join: columns must be a sequence of column names: {column} found instead What it means
Raised in selected_right_table_columns while validating the `columns` argument of Table.join in the Agate table emulation. The Jinja value passed as `columns` is not iterable (not a list/tuple of column-name strings), so try_iter() fails and the underlying type error is wrapped into this InvalidArgument message. The input at fault is the caller's `columns` keyword in the Jinja join() call.
Solutions
- Pass a sequence of column-name strings, e.g. table.join(other, left_key='id', right_key='id', columns=['name', 'amount'])
- Pass a list of strings rather than a single string, a dict, or an integer
- Omit `columns` entirely to select all non-key right-table columns
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/dbt-agate/src/join.rs:118 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/2b1564a70fd22277.
Report an issue: GitHub.
Appendix: source
Thrown at crates/dbt-agate/src/join.rs:118
//
// `None` means "all columns not in right_key" (the default), `Some([])` means
// "no columns", and `Some([name1, name2, ...])` means "only these columns".
fn selected_right_table_columns(columns: Option<&Value>) -> Result<Option<Vec<String>>, Error> {
let Some(columns) = columns else {
return Ok(None);
};
let iter = columns.try_iter().map_err(|e| {
Error::new(
ErrorKind::InvalidArgument,
format!("Table.join: columns must be a sequence of column names: {e}"),
)
})?;
let mut names = Vec::new();
for column in iter {
match column.as_str() {
Some(name) => names.push(name.to_string()),
None => {
return Err(Error::new(
ErrorKind::InvalidArgument,
format!(
"Table.join: columns must be a sequence of column names: {column} found instead"
),
));
}
}
}
Ok(Some(names))
}
impl AgateTable {
pub fn join(
&self,
right_table: &AgateTable,
left_key: Option<&Value>,
right_key: Option<&Value>,
join_type: JoinType,View on GitHub (pinned to 0267ce9170)