matplotlib/matplotlib · error · ValueError
Invalid vmin or vmax
Error message
Invalid vmin or vmax
What it means
For scale-backed norms (LogNorm, AsinhNorm, FuncNorm), __call__ transforms [vmin, vmax] through the scale and requires both results to be finite. With a log scale, a vmin or vmax <= 0 transforms to NaN/masked and raises 'Invalid vmin or vmax'. Data values outside the domain are only masked; it is the limits themselves that must be valid.
Source
Thrown at lib/matplotlib/colors.py:2957
inspect.Parameter("self", inspect.Parameter.POSITIONAL_OR_KEYWORD),
*bound_init_signature.parameters.values()])
def __call__(self, value, clip=None):
value, is_scalar = self.process_value(value)
if self.vmin is None or self.vmax is None:
self.autoscale_None(value)
if self.vmin > self.vmax:
raise ValueError("vmin must be less or equal to vmax")
if self.vmin == self.vmax:
return np.full_like(value, 0)
if clip is None:
clip = self.clip
if clip:
value = np.clip(value, self.vmin, self.vmax)
t_value = self._trf.transform(value).reshape(np.shape(value))
t_vmin, t_vmax = self._trf.transform([self.vmin, self.vmax])
if not np.isfinite([t_vmin, t_vmax]).all():
raise ValueError("Invalid vmin or vmax")
t_value -= t_vmin
t_value /= (t_vmax - t_vmin)
t_value = np.ma.masked_invalid(t_value, copy=False)
return t_value[0] if is_scalar else t_value
def inverse(self, value):
if not self.scaled():
raise ValueError("Not invertible until scaled")
if self.vmin > self.vmax:
raise ValueError("vmin must be less or equal to vmax")
t_vmin, t_vmax = self._trf.transform([self.vmin, self.vmax])
if not np.isfinite([t_vmin, t_vmax]).all():
raise ValueError("Invalid vmin or vmax")
value, is_scalar = self.process_value(value)
rescaled = value * (t_vmax - t_vmin)
rescaled += t_vmin
value = (self._trf
.inverted()View on GitHub (pinned to b379c1b69e)
Solutions
- Use strictly positive limits: vmin = max(vmin, smallest_positive_value)
- For zero-crossing data use SymLogNorm(linthresh=...) or AsinhNorm instead of LogNorm
- Let autoscale derive limits from the positive values rather than pinning vmin=0
Example fix
# before norm = LogNorm(vmin=0, vmax=100) # ValueError # after norm = LogNorm(vmin=1e-3, vmax=100) # or for data crossing zero: norm = SymLogNorm(linthresh=1e-3, vmin=-100, vmax=100)
Defensive patterns
Strategy: validation
Validate before calling
if norm.__class__.__name__ == 'LogNorm' and (vmin <= 0 or vmax <= 0):
raise ValueError(f'LogNorm limits must be positive; got vmin={vmin}, vmax={vmax}')
normed = norm(data) Type guard
def lognorm_range_ok(vmin, vmax) -> bool:
return vmin > 0 and vmax > 0 and vmin <= vmax Try / catch
try:
normed = norm(data)
except ValueError as e:
if 'Invalid vmin or vmax' in str(e) and isinstance(norm, LogNorm):
norm = SymLogNorm(linthresh=max(vmin, 1e-3), vmin=vmin, vmax=vmax)
normed = norm(data)
else:
raise Prevention
- Never pin vmin=0 on log scales; clamp to the smallest positive value
- Use SymLogNorm or AsinhNorm for data that includes or crosses zero
- Validate positivity where the norm is built so both __call__ and inverse are safe
When it happens
Trigger: LogNorm(vmin=0, vmax=100)(data); LogNorm(vmin=-5, vmax=5); pinning vmax=0 for all-negative data; FuncNorm whose inverse is undefined at the chosen limits.
Common situations: Log-scaling datasets bounded by zero (copying linear-norm limits into log plots); choropleth/count data where 0 was the old vmin; defaults that insert 0 as the lower bound.
Related errors
- vmin must be less or equal to vmax
- Wedge sizes must be finite numbers
- x and y arguments to pcolormesh cannot have non-finite value
- ecdf() does not support NaNs
- aspect must be finite and positive
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/b61b64fd56c3b0a4.
Report an issue: GitHub.