pola-rs/polars · error
should be hashable
Error message
should be hashable
What it means
ObjectValue wraps an arbitrary Python object stored in an Object-dtype column. Its Hash implementation calls Python's hash() on the wrapped value; if that value is unhashable (dict, list, set — anything with __hash__ = None), the Python call fails and this expect panics with 'should be hashable'.
Source
Thrown at crates/polars-python/src/conversion/mod.rs:753
}
#[derive(Debug)]
#[repr(transparent)]
pub struct ObjectValue {
pub inner: Py<PyAny>,
}
impl Clone for ObjectValue {
fn clone(&self) -> Self {
Python::attach(|py| Self {
inner: self.inner.clone_ref(py),
})
}
}
impl Hash for ObjectValue {
fn hash<H: Hasher>(&self, state: &mut H) {
let h = Python::attach(|py| self.inner.bind(py).hash().expect("should be hashable"));
state.write_isize(h)
}
}
impl Eq for ObjectValue {}
impl PartialEq for ObjectValue {
fn eq(&self, other: &Self) -> bool {
Python::attach(|py| {
match self
.inner
.bind(py)
.rich_compare(other.inner.bind(py), CompareOp::Eq)
{
Ok(result) => result.is_truthy().unwrap(),
Err(_) => false,
}
})View on GitHub (pinned to df599052da)
Solutions
- Cast the Object column to String (e.g. via map to repr/json) before group_by/unique/join
- If using custom classes, define both __eq__ and __hash__ consistently
- Avoid storing unhashable values in Object columns destined for key-based operations
- Use a struct column instead of objects when the data is record-shaped
Example fix
# before
(df.group_by(pl.col("obj")).agg(pl.len())) # obj holds dicts -> panic 'should be hashable'
# after
df.group_by(pl.col("obj").map_elements(lambda v: repr(v), return_dtype=pl.String)).agg(pl.len())
# or on the class side
class Key:
def __init__(self, v): self.v = v
def __eq__(self, o): return isinstance(o, Key) and o.v == self.v
def __hash__(self): return hash(self.v) Defensive patterns
Strategy: type-guard
Validate before calling
# Python: verify object column is hashable before hash-based ops
def column_is_hashable(s: pl.Series) -> bool:
return all(is_hashable(v) for v in s.head(100).to_list())
from collections.abc import Hashable
def is_hashable(v) -> bool:
try:
hash(v)
return True
except TypeError:
return False Type guard
def is_hashable(v) -> bool:
try:
hash(v); return True
except TypeError:
return False Prevention
- Avoid Object dtype for group-by/join keys; use String or Struct
- Define __hash__ whenever you define __eq__ on stored classes
- Convert unhashable values to a canonical string form up front
When it happens
Trigger: Any hash-based operation on an Object column containing unhashable Python values: group_by, unique/n_unique, joins on that column, is_duplicated, value_counts.
Common situations: Columns built from Python dicts/lists/objects (e.g. via apply returning complex values) then used as group-by or join keys; user classes that define __eq__ without __hash__ (Python then sets __hash__ to None).
Related errors
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/c2c5fbcc8f19fa5b.
Report an issue: GitHub.