matplotlib/matplotlib · error · ValueError
position[0] should be one of 'outward', 'axes', or 'data'
Error message
position[0] should be one of 'outward', 'axes', or 'data'
What it means
After checking the tuple length, Spine.set_position requires position[0] to be one of 'outward', 'axes', 'data'. This second ValueError fires when the first element is misspelled or wrongly cased ('Data', 'axis'), or when the tuple order is swapped, e.g. (0, 'data').
Source
Thrown at lib/matplotlib/spines.py:354
* 'axes': place the spine at the specified Axes coordinate (0 to 1).
* 'data': place the spine at the specified data coordinate.
Additionally, shorthand notations define a special positions:
* 'center' -> ``('axes', 0.5)``
* 'zero' -> ``('data', 0.0)``
Examples
--------
:doc:`/gallery/spines/spine_placement_demo`
"""
if position in ('center', 'zero'): # special positions
pass
else:
if len(position) != 2:
raise ValueError("position should be 'center' or 2-tuple")
if position[0] not in ['outward', 'axes', 'data']:
raise ValueError("position[0] should be one of 'outward', "
"'axes', or 'data' ")
self._position = position
self.set_transform(self.get_spine_transform())
if self.axis is not None:
self.axis.reset_ticks()
self.stale = True
def get_position(self):
"""Return the spine position."""
self._ensure_position_is_set()
return self._position
def get_spine_transform(self):
"""Return the spine transform."""
self._ensure_position_is_set()
position = self._position
if isinstance(position, str):View on GitHub (pinned to b379c1b69e)
Solutions
- Use exactly 'outward', 'axes', or 'data' as the first element and the numeric amount as the second
- Validate the first element against the allowed set before calling set_position
- Prefer the 'center'/'zero' shorthands when applicable, which bypass this check
Example fix
# before
ax.spines['bottom'].set_position(('Data', 0)) # wrong case
ax.spines['bottom'].set_position((0, 'data')) # swapped order
# after
ax.spines['bottom'].set_position(('data', 0)) Defensive patterns
Strategy: type-guard
Validate before calling
POSITION_TYPES = {'outward', 'axes', 'data'}
if isinstance(pos, tuple) and len(pos) == 2:
pos = (pos[0].lower() if isinstance(pos[0], str) else pos[0], pos[1])
assert pos[0] in POSITION_TYPES, f'bad position type: {pos[0]!r}' Type guard
def has_valid_position_type(pos) -> bool:
return isinstance(pos, tuple) and len(pos) == 2 and pos[0] in ('outward', 'axes', 'data') Prevention
- Keep the order fixed: (position_type, amount), never (amount, position_type)
- Use lowercase type names exactly as documented
- Whitelist-check position types when they come from themes or user input
When it happens
Trigger: set_position(('Data', 0)); set_position((0.5, 'axes')); set_position(('outwards', 5)).
Common situations: Case typos in hand-written theme dicts; tuples built by unpacking in the wrong order; position vocabularies ported from plotting libraries that use different type names.
Related errors
- position should be 'center' or 2-tuple
- spine_type: {self.spine_type} not supported
- unable to set bounds for spine "%s"
- Multiple spines must be passed as a single list
- Spines does not support slicing except for the fully open sl
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/0b2008245264043a.
Report an issue: GitHub.