matplotlib/matplotlib · error · ValueError
unknown spine spine_type: {self.spine_type!r}
Error message
unknown spine spine_type: {self.spine_type!r} What it means
Spine.get_spine_transform selects the spine's base transform from spine_type: get_yaxis_transform(which='grid') for 'left'/'right' and get_xaxis_transform(which='grid') for 'top'/'bottom'. No other type has a branch, so a ValueError is raised. set_position() always calls get_spine_transform, and even get_position() triggers it lazily through _ensure_position_is_set, so any position operation on a custom-typed spine raises this error.
Source
Thrown at lib/matplotlib/spines.py:386
"""Return the spine transform."""
self._ensure_position_is_set()
position = self._position
if isinstance(position, str):
if position == 'center':
position = ('axes', 0.5)
elif position == 'zero':
position = ('data', 0)
assert len(position) == 2, 'position should be 2-tuple'
position_type, amount = position
_api.check_in_list(['axes', 'outward', 'data'],
position_type=position_type)
if self.spine_type in ['left', 'right']:
base_transform = self.axes.get_yaxis_transform(which='grid')
elif self.spine_type in ['top', 'bottom']:
base_transform = self.axes.get_xaxis_transform(which='grid')
else:
raise ValueError(f'unknown spine spine_type: {self.spine_type!r}')
if position_type == 'outward':
if amount == 0: # short circuit commonest case
return base_transform
else:
offset_vec = {'left': (-1, 0), 'right': (1, 0),
'bottom': (0, -1), 'top': (0, 1),
}[self.spine_type]
# calculate x and y offset in dots
offset_dots = amount * np.array(offset_vec) / 72
return (base_transform
+ mtransforms.ScaledTranslation(
*offset_dots, self.get_figure(root=False).dpi_scale_trans))
elif position_type == 'axes':
if self.spine_type in ['left', 'right']:
# keep y unchanged, fix x at amount
return (mtransforms.Affine2D.from_values(0, 0, 0, 1, amount, 0)
+ base_transform)View on GitHub (pinned to b379c1b69e)
Solutions
- Guard by spine_type: only call set_position/get_position on 'left', 'right', 'top', 'bottom' spines
- Override set_position, get_position, and get_spine_transform together in the Spine subclass (cartopy raises NotImplementedError from set_position)
- Register the spine under a standard type if it genuinely should support Cartesian positioning
Example fix
# before
spine = Spine(ax, 'geo', path)
spine.set_position(('outward', 5)) # ValueError: unknown spine spine_type: 'geo'
# after
class GeoSpine(Spine):
def set_position(self, position):
raise NotImplementedError('projection spine cannot be repositioned')
def get_spine_transform(self):
return self.axes.transAxes
spine = GeoSpine(ax, 'geo', path) Defensive patterns
Strategy: type-guard
Validate before calling
CARTESIAN = ('left', 'right', 'top', 'bottom')
# guard generic styling loops
for spine in ax.spines.values():
if getattr(spine, 'spine_type', '') in CARTESIAN:
spine.set_position(('outward', 5)) Type guard
def can_position_spine(spine) -> bool:
return getattr(spine, 'spine_type', None) in ('left', 'right', 'top', 'bottom') Try / catch
try:
spine.set_position(pos)
except ValueError as err:
if 'unknown spine spine_type' in str(err):
pass # projection/custom spine: positioning not supported, skip
else:
raise Prevention
- Treat set_position/get_position as Cartesian-spine-only APIs
- In Spine subclasses with custom types, override set_position and get_spine_transform together
- Style projection spines through their Axes APIs (theta offset, extent), not spine positions
When it happens
Trigger: spine.set_position(pos) or spine.get_position() on a Spine whose spine_type is a custom name such as 'geo'; generic code that applies the position machinery to every spine including projection spines.
Common situations: Cartopy-style GeoSpine and other projection spines carry custom spine_types; matplotlib core deliberately never calls the position machinery on non-Cartesian spines (see _ensure_transform_is_set), but user styling helpers that do hit this error.
Related errors
- spine_type: {self.spine_type} not supported
- unable to make path for spine "%s"
- 'transform' is not allowed as a keyword argument; axhline ge
- 'transform' is not allowed as a keyword argument; axvline ge
- unknown value for which: {which!r}
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/23401fb530ebd49b.
Report an issue: GitHub.