{"record":{"id":"0b2008245264043a","repo":"matplotlib/matplotlib","slug":"position-0-should-be-one-of-outward-axes-or","errorCode":null,"errorMessage":"position[0] should be one of 'outward', 'axes', or 'data' ","messagePattern":"position\\[0\\] should be one of 'outward', 'axes', or 'data' ","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/matplotlib/spines.py","lineNumber":354,"sourceCode":"        * 'axes': place the spine at the specified Axes coordinate (0 to 1).\n        * 'data': place the spine at the specified data coordinate.\n\n        Additionally, shorthand notations define a special positions:\n\n        * 'center' -> ``('axes', 0.5)``\n        * 'zero' -> ``('data', 0.0)``\n\n        Examples\n        --------\n        :doc:`/gallery/spines/spine_placement_demo`\n        \"\"\"\n        if position in ('center', 'zero'):  # special positions\n            pass\n        else:\n            if len(position) != 2:\n                raise ValueError(\"position should be 'center' or 2-tuple\")\n            if position[0] not in ['outward', 'axes', 'data']:\n                raise ValueError(\"position[0] should be one of 'outward', \"\n                                 \"'axes', or 'data' \")\n        self._position = position\n        self.set_transform(self.get_spine_transform())\n        if self.axis is not None:\n            self.axis.reset_ticks()\n        self.stale = True\n\n    def get_position(self):\n        \"\"\"Return the spine position.\"\"\"\n        self._ensure_position_is_set()\n        return self._position\n\n    def get_spine_transform(self):\n        \"\"\"Return the spine transform.\"\"\"\n        self._ensure_position_is_set()\n\n        position = self._position\n        if isinstance(position, str):","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/matplotlib/matplotlib/blob/b379c1b69e012b142c0f496a52bcb30513802d72/lib/matplotlib/spines.py#L336-L372","documentation":"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').","triggerScenarios":"set_position(('Data', 0)); set_position((0.5, 'axes')); set_position(('outwards', 5)).","commonSituations":"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.","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"],"exampleFix":"# before\nax.spines['bottom'].set_position(('Data', 0))  # wrong case\nax.spines['bottom'].set_position((0, 'data'))   # swapped order\n\n# after\nax.spines['bottom'].set_position(('data', 0))","handlingStrategy":"type-guard","validationCode":"POSITION_TYPES = {'outward', 'axes', 'data'}\n\nif isinstance(pos, tuple) and len(pos) == 2:\n    pos = (pos[0].lower() if isinstance(pos[0], str) else pos[0], pos[1])\nassert pos[0] in POSITION_TYPES, f'bad position type: {pos[0]!r}'","typeGuard":"def has_valid_position_type(pos) -> bool:\n    return isinstance(pos, tuple) and len(pos) == 2 and pos[0] in ('outward', 'axes', 'data')","tryCatchPattern":null,"preventionTips":["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"],"tags":["matplotlib","spines","position","valueerror"],"backgroundTag":"invalid-spine-position","analyzedSha":"b379c1b69e012b142c0f496a52bcb30513802d72","analyzedAt":"2026-08-21T23:31:55.468Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}