matplotlib/matplotlib · error · TypeError
np.datetime64 'position' values require np.timedelta64 'widt
Error message
np.datetime64 'position' values require np.timedelta64 'widths'
What it means
TypeError raised by the shared violinplot validation when positions[0] is a numpy datetime64 but widths[0] is not a numpy timedelta64. This is the numpy twin of the datetime/date check, with one extra trap: a plain Python datetime.timedelta is NOT an instance of np.timedelta64, so date positions converted to numpy with .to_numpy() plus Python-timedelta widths still fails.
Source
Thrown at lib/matplotlib/axes/_axes.py:9293
widths = [widths] * N
elif len(widths) != N:
raise ValueError(datashape_message.format("widths"))
# For usability / better error message:
# Validate that datetime-like positions have timedelta-like widths.
# Checking only the first element is good enough for standard misuse cases
if N > 0: # No need to validate if there is no data
pos0 = positions[0]
width0 = widths[0]
if (isinstance(pos0, (datetime.datetime, datetime.date))
and not isinstance(width0, datetime.timedelta)):
raise TypeError(
"datetime/date 'position' values require timedelta 'widths'. "
"For example, use positions=[datetime.date(2024, 1, 1)] "
"and widths=[datetime.timedelta(days=1)].")
elif (isinstance(pos0, np.datetime64)
and not isinstance(width0, np.timedelta64)):
raise TypeError(
"np.datetime64 'position' values require np.timedelta64 'widths'")
_api.check_in_list(["both", "low", "high"], side=side)
# Calculate ranges for statistics lines (shape (2, N)).
line_ends = [[-0.25 if side in ['both', 'low'] else 0],
[0.25 if side in ['both', 'high'] else 0]] \
* np.array(widths) + positions
# Make a cycle of color to iterate through, using 'none' as fallback
def cycle_color(color, alpha=None):
rgba = mcolors.to_rgba_array(color, alpha=alpha)
color_cycler = itertools.chain(itertools.cycle(rgba),
itertools.repeat('none'))
color_list = []
for _ in range(N):
color_list.append(next(color_cycler))
return color_list
View on GitHub (pinned to b379c1b69e)
Solutions
- Use numpy timedelta widths: widths=np.timedelta64(1, 'D') (scalar broadcasts).
- Convert existing Python timedeltas: np.timedelta64(pd.Timedelta(days=1)) or np.timedelta64(datetime.timedelta(days=1)).
- Alternatively convert positions to floats via matplotlib.dates.date2num and keep numeric widths.
Example fix
# before
ax.violinplot(data, positions=daily_index.to_numpy(), widths=0.5)
# after
ax.violinplot(data, positions=daily_index.to_numpy(),
widths=np.timedelta64(1, 'D')) Defensive patterns
Strategy: type-guard
Validate before calling
import numpy as np
def coerce_violin_widths_np(positions, widths):
"""np.datetime64 positions need np.timedelta64 widths (not datetime.timedelta)."""
n = len(positions)
widths = [widths] * n if np.isscalar(widths) else list(widths)
if isinstance(positions[0], np.datetime64):
widths = [w if isinstance(w, np.timedelta64)
else np.timedelta64(w, 'D') for w in widths]
return widths Type guard
import numpy as np
def violin_np_datetime_ok(positions, widths) -> bool:
if len(positions) == 0:
return True
w0 = widths if np.isscalar(widths) else widths[0]
if isinstance(positions[0], np.datetime64):
return isinstance(w0, np.timedelta64) # datetime.timedelta does NOT count
return True Try / catch
try:
ax.violinplot(data, positions=positions, widths=widths)
except TypeError as e:
if 'np.datetime64' in str(e):
ax.violinplot(data, positions=positions,
widths=np.timedelta64(1, 'D'))
else:
raise Prevention
- Remember a Python datetime.timedelta is not a np.timedelta64 for this check.
- Convert explicitly: np.timedelta64(pd.Timedelta(days=1)).
- Use matplotlib.dates.date2num positions to keep everything numeric.
When it happens
Trigger: ax.violinplot(data, positions=daily_index.to_numpy(), widths=0.5); positions of dtype datetime64 combined with widths=[datetime.timedelta(days=1)] (Python timedelta instead of np.timedelta64).
Common situations: Pandas DatetimeIndex values converted to numpy datetime64; time-indexed box/violin charts after a pandas-to-numpy conversion where widths were written for the Python datetime branch.
Related errors
- datetime/date 'position' values require timedelta 'widths'.
- 'slope' cannot be used with non-linear scales
- Cannot pass 'drawstyle' or 'ds' to ecdf()
- Invalid shape {Z.shape} for image data
- List of violinplot statistics and `positions` values must ha
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/7ffd41d5a0f3d43d.
Report an issue: GitHub.