dbt-labs/dbt-core · error
ColumnsAsTuple::index_of
Error message
ColumnsAsTuple::index_of
What it means
`ColumnsAsTuple::index_of` in dbt-agate is a `todo!()` placeholder in the `TupleRepr` trait implementation, so calling it panics with "ColumnsAsTuple::index_of". The columns-as-tuple view cannot yet locate the position of a value among a table's columns. Any tuple-style `index_of` lookup against the table's column collection panics.
Source
Thrown at crates/dbt-agate/src/columns.rs:216
}
}
impl TupleRepr for ColumnsAsTuple {
fn get_item_by_index(&self, idx: isize) -> Option<Value> {
let column = self.of_table.get_column(idx)?;
Some(Value::from_object(column))
}
fn len(&self) -> usize {
self.of_table.num_columns()
}
fn count_occurrences_of(&self, _needle: &Value) -> usize {
todo!("ColumnsAsTuple::count_occurrences_of")
}
fn index_of(&self, _needle: &Value) -> Option<usize> {
todo!("ColumnsAsTuple::index_of")
}
fn clone_repr(&self) -> Box<dyn TupleRepr> {
Box::new(ColumnsAsTuple {
of_table: Arc::clone(&self.of_table),
})
}
}
/// Represents an instance of a `MappedSequence` populated by a list of columns.
///
/// https://github.com/wireservice/agate/blob/7023e35b51e8abfe9784fe292a23dd4d7d983c63/agate/table/__init__.py#L181
#[derive(Debug)]
pub struct Columns {
/// Internal representation of the columns sequence is the table representation itself.
of_table: Arc<TableRepr>,
}
View on GitHub (pinned to 0267ce9170)
Solutions
- Avoid `index_of` on the columns tuple view; find the column position by iterating column names/values manually.
- Use a representation that implements `index_of` (e.g., row tuples) if applicable.
- Implement the method upstream: iterate columns in order and return `Some(i)` for the first column equal to the needle, else `None`.
Example fix
// before (crates/dbt-agate/src/columns.rs)
fn index_of(&self, _needle: &Value) -> Option<usize> {
todo!("ColumnsAsTuple::index_of")
}
// after
fn index_of(&self, needle: &Value) -> Option<usize> {
(0..self.len()).find(|&i| self.get(i).map_or(false, |v| v == needle))
} Defensive patterns
Strategy: validation
Validate before calling
// avoid the call; find the column position manually:
let idx = (0..table.num_columns())
.find(|&i| table.column_value(i) == *needle); Type guard
fn supports_index_of(repr: &dyn TupleRepr) -> bool {
(repr as &dyn std::any::Any).downcast_ref::<ColumnsAsTuple>().is_none()
} Try / catch
// isolate the placeholder if unavoidable:
let idx = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| repr.index_of(&needle)))
.unwrap_or(None); Prevention
- Look up column positions via column names/indices instead of tuple-style index_of.
- Use representations whose TupleRepr methods are fully implemented.
- Grep for todo!() in dbt-agate before relying on a trait method for ColumnsAsTuple.
When it happens
Trigger: Calling `index_of(&value)` on a `ColumnsAsTuple` for any needle value, e.g., asking which column equals a given value.
Common situations: Porting Python agate code that calls `.index(...)` on a table's columns tuple to the Rust dbt-agate port; generic tuple-repr algorithms that fall back to `index_of`.
Related errors
- ColumnsAsTuple::count_occurrences_of
- column_distinct
- group_by with function key
- ReplayStatement::bind
- ReplayStatement::bind_stream
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/ef7f7193ae6e64c2.
Report an issue: GitHub.