dbt-labs/dbt-core · error · minijinja::Error::InvalidOperation
svv_columns must be an AgateTable
Error message
svv_columns must be an AgateTable
What it means
The same catalog builder also requires the `svv_columns` argument to be a single AgateTable (the SVV_REDSHIFT_COLUMNS snapshot). This error is raised when downcasting that argument fails. The library enforces this so column metadata joins against the show-tables tables use the agate table API.
Source
Thrown at crates/dbt-adapter/src/adapter/mod.rs:571
&["show_tables_results", "svv_columns"],
args,
);
let show_tables_value = iter.next_arg::<&Value>()?;
let mut show_tables_results: Vec<Arc<AgateTable>> = Vec::new();
for table_value in show_tables_value.try_iter()? {
let table = table_value.downcast_object::<AgateTable>().ok_or_else(|| {
minijinja::Error::new(
minijinja::ErrorKind::InvalidOperation,
"show_tables_results must contain AgateTables",
)
})?;
show_tables_results.push(table);
}
let svv_columns = iter
.next_arg::<&Value>()?
.downcast_object::<AgateTable>()
.ok_or_else(|| {
minijinja::Error::new(
minijinja::ErrorKind::InvalidOperation,
"svv_columns must be an AgateTable",
)
})?;
iter.finish()?;
let catalog = adapter.build_catalog_from_show_tables_and_svv_columns(
&show_tables_results,
svv_columns,
)?;
Ok(Value::from_object(catalog))
}
// During parse phase queries don't execute, so there are no real tables to join.
Parse(_) => Ok(Value::from_object(AgateTable::default())),
}
}
/// Encloses identifier in the correct quotes for the adapter when escaping reserved column names etc.View on GitHub (pinned to 0267ce9170)
Solutions
- Convert the SVV columns result with load_agate_table() before calling the builder
- Verify argument order: show_tables_results first, then svv_columns
- If the SVV query returned nothing, pass an empty AgateTable rather than None or a dict
Example fix
// before
svv_columns = cursor.fetchall()
// after
svv_columns = load_agate_table({'column': [{'name': d[0], 'data_type': d[1]} for d in cursor.fetchall()]}) Defensive patterns
Strategy: type-guard
Validate before calling
# python guard before the call
if svv_columns is None or not hasattr(svv_columns, 'column_names'):
svv_columns = load_agate_table(svv_rows) Type guard
fn is_agate_table(v: &Value) -> bool {
v.downcast_object::<AgateTable>().is_some()
} Try / catch
match svv_value.downcast_object::<AgateTable>() {
Some(t) => build_catalog(show_tables_results, t),
None => Err(minijinja::Error::new(minijinja::ErrorKind::InvalidOperation, "svv_columns must be an AgateTable")),
} Prevention
- Load SVV_REDSHIFT_COLUMNS output through load_agate_table() before catalog building
- Confirm argument ordering matches the function signature
- Pass an empty AgateTable rather than None when the SVV query returns no rows
When it happens
Trigger: Passing anything other than an AgateTable as the `svv_columns` argument to build_catalog_from_show_tables_and_svv_columns — e.g. a dict, list of rows, or serialized JSON of SVV_REDSHIFT_COLUMNS.
Common situations: Custom Redshift catalog scripts feed SVV query output directly as Python dicts; or argument order was swapped so the wrong value lands in the svv_columns slot.
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
- show_tables_results must contain AgateTables
- list_relations_schemas_by_patterns for Redshift
- ColumnsAsTuple::count_occurrences_of
- ColumnsAsTuple::index_of
- column_distinct
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/8d42ae81bad941c8.
Report an issue: GitHub.