dbt-labs/dbt-core · error · InvalidOperation

Table.distinct: {e}

Error message

Table.distinct: {e}

What it means

Thrown by the `Table.distinct()` method binding when the underlying `distinct(key)` operation fails, wrapping the inner error as an InvalidOperation error prefixed with `Table.distinct:`. Distinct requires an optional key that resolves to valid column(s); failures come from the internal deduplication step, e.g. an unknown key column.

Source

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

                            Some(vec![s.to_string()])
                        } else if let Ok(iter) = v.try_iter() {
                            let mut keys = Vec::new();
                            for key in iter {
                                match key.as_str() {
                                    Some(s) => keys.push(s.to_string()),
                                    None => unimplemented!("distinct with non-string keys"),
                                }
                            }
                            Some(keys)
                        } else {
                            None
                        }
                    }
                    None => None,
                };

                let result = self.as_ref().distinct(key).map_err(|e| {
                    Error::new(ErrorKind::InvalidOperation, format!("Table.distinct: {e}"))
                })?;
                Ok(Value::from_object(result))
            }
            other => unimplemented!("AgateTable::{}", other),
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::flat_record_batch::FlatRecordBatch;
    use crate::test_fixtures::*;
    use crate::*;
    use arrow::array::{
        ArrayRef, BooleanBuilder, DictionaryArray, Float64Builder, Int32Array, Int32Builder,
        ListBuilder, StringBuilder, StringViewBuilder, StructBuilder,
    };
    use arrow::array::{GenericListArray, StringArray};

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Read the wrapped inner message after `Table.distinct:` for the root cause
  2. Verify the key column exists: `key in table.column_names`
  3. Call `distinct()` with no argument to dedupe on all columns
  4. Use a string column name (or list of names) for the key

Example fix

// before
table.distinct('catgory')  # typo
// after
assert 'category' in table.column_names
table.distinct('category')
Defensive patterns

Strategy: validation

Validate before calling

if key is not None and key not in table.column_names:
    raise ValueError(f'distinct key {key!r} not in {table.column_names}')

Type guard

null

Try / catch

try:
    result = table.distinct(key)
except Exception as e:
    if str(e).startswith('Table.distinct:'):
        raise ValueError(f'cannot compute distinct on {key!r}: {e}') from e
    raise

Prevention

When it happens

Trigger: Calling `table.distinct(key)` where the internal `distinct` returns an error — typically `key` names a column that does not exist or a key of unsupported form, or the dedup row-index computation fails.

Common situations: Misspelled column name in the distinct key; column dropped by a prior select/limit chain; ported code passing a column index instead of a name.

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