dbt-labs/dbt-core · error
ColumnsAsTuple::count_occurrences_of
Error message
ColumnsAsTuple::count_occurrences_of
What it means
`ColumnsAsTuple::count_occurrences_of` in dbt-agate is a `todo!()` placeholder in the `TupleRepr` trait implementation, so calling it panics with the message "ColumnsAsTuple::count_occurrences_of". The columns-as-tuple view of a Table does not yet support counting occurrences of a value across its columns. Any code that treats a table's columns like an agate Python tuple and asks how many entries equal a given value will hit this panic.
Source
Thrown at crates/dbt-agate/src/columns.rs:212
}
pub fn into_tuple(self) -> Tuple {
Tuple(Box::new(self))
}
}
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 {View on GitHub (pinned to 0267ce9170)
Solutions
- Avoid calling `count_occurrences_of` on the columns tuple view; iterate the table's rows/values and count manually instead.
- Use the row-oriented tuple representation instead of `ColumnsAsTuple` if the operation is available there.
- Implement the method upstream: delegate to comparing each column against the needle (per the Python agate semantics) and return the match count.
Example fix
// before (crates/dbt-agate/src/columns.rs)
fn count_occurrences_of(&self, _needle: &Value) -> usize {
todo!("ColumnsAsTuple::count_occurrences_of")
}
// after
fn count_occurrences_of(&self, needle: &Value) -> usize {
(0..self.len()).filter(|i| self.get(i).map_or(false, |v| v == needle)).count()
} Defensive patterns
Strategy: validation
Validate before calling
// avoid the call entirely; count manually:
let count = table.rows()
.filter(|row| row.values().iter().any(|v| v == &needle))
.count(); Type guard
fn supports_tuple_repr_op(repr: &dyn TupleRepr) -> bool {
// ColumnsAsTuple does not implement count_occurrences_of/index_of
(repr as &dyn std::any::Any).downcast_ref::<ColumnsAsTuple>().is_none()
} Try / catch
// isolate the placeholder if a trait object must be used:
let n = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| repr.count_occurrences_of(&needle)))
.unwrap_or(0); Prevention
- Do not use the columns tuple view for value multiplicity checks; use row/column iteration.
- Prefer row-oriented tuple representations when you need full TupleRepr behavior.
- Check the dbt-agate TODO markers before porting agate Python tuple methods.
When it happens
Trigger: Calling `count_occurrences_of(&value)` on a `ColumnsAsTuple` (e.g., a table's `.columns` view used as a tuple) for any needle value.
Common situations: Porting agate Python table operations (e.g., `values.count(...)`) to the Rust dbt-agate port; code doing membership/multiplicity checks on a table's column collection.
Related errors
- ColumnsAsTuple::index_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/cd17abcab391c0c1.
Report an issue: GitHub.