pola-rs/polars · error
can only use timedelta string language with…
Error message
can only use timedelta string language with Date/Datetime/Duration/Time dtypes
What it means
Polars throws this panic when a string tolerance passed to a join is parsed as a 'timedelta string language' value (e.g. "2d") but the join key dtype is not temporal. The string tolerance only makes sense for Date/Datetime/Duration/Time join columns. Raised in `resolve_join` (called by `resolve_join_where`) in crates/polars-plan/src/plans/conversion/dsl_to_ir/join.rs.
Solutions
- Cast the join key column to Datetime (or Date/Duration/Time) before joining
- Remove the string tolerance argument, or pass a numeric tolerance matching the key dtype
- Verify the join key dtypes with df.schema / df.dtypes before the join
Example fix
// before
df.join(other, on="ts", tolerance="2d") // ts is Int64 epoch millis
// after
df.with_columns(pl.col("ts").cast(pl.Datetime("ms")))
.join(other, on="ts", tolerance="2d") Defensive patterns
Strategy: validation
Validate before calling
schema = lf.collect_schema()
dtype = schema["ts"]
assert dtype in (pl.Date, pl.Datetime, pl.Duration, pl.Time), f"tolerance string requires temporal join key, got {dtype}" Type guard
def is_temporal(dtype: pl.DataType) -> bool:
return dtype in (pl.Date, pl.Datetime, pl.Duration, pl.Time) Try / catch
try:
result = lf.join(other, on="ts", tolerance="2d").collect()
except pl.exceptions.PanicException as e:
if "timedelta string language" in str(e):
result = lf.with_columns(pl.col("ts").cast(pl.Datetime("us"))).join(other, on="ts", tolerance="2d").collect()
else:
raise Prevention
- Check join key dtypes with collect_schema() before using string tolerance
- Prefer explicit Duration/numeric tolerance over string 'timedelta language'
- Cast epoch-millis integer timestamps to Datetime at ingestion
When it happens
Trigger: Calling `join(..., tolerance="2d")` (or join_where with tolerance_str) where the join key column dtype is an integer, string, float, etc., instead of a Date/Datetime/Duration/Time dtype.
Common situations: Using an asof-join style tolerance on integer timestamp columns (epoch millis), or after a schema change that converted a datetime column to a string/int.
Related errors
- cross join filter holds no keys
- 'join_where' requires at least one predicate
- activate dtype
- addition overflow: +
- cannot coerce datatypes
AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18).
Data as JSON: /api/errors/35bfd5989dffa8e4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/polars-plan/src/plans/conversion/dsl_to_ir/join.rs:398
{
Datetime(tu, _) | Duration(tu) => {
let tolerance = match tu {
TimeUnit::Nanoseconds => duration.duration_ns(),
TimeUnit::Microseconds => duration.duration_us(),
TimeUnit::Milliseconds => duration.duration_ms(),
};
options.tolerance = Some(Scalar::from(tolerance))
},
Date => {
let days = (duration.duration_ms() / MILLISECONDS_IN_DAY) as i32;
options.tolerance = Some(Scalar::from(days))
},
Time => {
let tolerance = duration.duration_ns();
options.tolerance = Some(Scalar::from(tolerance))
},
_ => {
panic!(
"can only use timedelta string language with Date/Datetime/Duration/Time dtypes"
)
},
}
}
}
// These are Arc<Schema>, into_owned is free.
let schema_left = schema_left.into_owned();
let schema_right = schema_right.into_owned();
options.options = {
let on = left_on.into_iter().zip(right_on).collect();
match &options.args.how {
#[cfg(feature = "asof_join")]
JoinType::AsOf(_) => JoinTypeOptionsIR::AsOf { on },
_ => JoinTypeOptionsIR::Equi {
on,View on GitHub (pinned to fe841f959e)