GeezerVison is showing github.com — [Bug]: Modifying NumPy array after passing to set_xticks() unexpectedly alters plot ticks · Issue #32313 · matplotlib/matplotlib
[Bug]: Modifying NumPy array after passing to set_xticks() unexpectedly alters plot ticks #32313DescriptionBug summary
When passing a NumPy array to ax.set_xticks(), Matplotlib retains a reference to the array instead of creating a copy. Any in-place modifications made to the array after calling set_xticks() directly mutate the plot's tick locations. Passing a standard Python list does not exhibit this issue, suggesting Matplotlib should create an explicit copy of array input internally.
Code for reproduction
import numpy as np
import matplotlib.pyplot as plt
attributes = ['Speed', 'Reliability', 'Comfort', 'Safety', 'Efficiency']
fig = plt.figure()
ax1 = fig.add_subplot(2, 1, 1, projection='polar')
theta = np.linspace(0, 2*np.pi, 5, endpoint=False)
# theta = np.linspace(0, 2*np.pi, 5, endpoint=False).tolist() # this works
ax1.set_xticks(theta)
ax1.set_xticklabels(attributes)
for i in range(5): theta[i] += np.pi * 2
Actual outcome
Expected outcome
Additional information
No response
Operating system
No response
Matplotlib Version
0.2.0.dev55193+unknown.g2153774ae
Matplotlib Backend
No response
Python version
No response
Jupyter version
No response
Installation
None Activitytimhoffm commented on Sep 7, 2026 @williamlus are these actual production bugs you are stumbling over or are you running tools that inverstigate theoretical error paths.
On the array-modification topic: I'm unclear whether we have a general guarantee that we isolate from passed parameters. Sometimes we do explicitly, but this is really a can of worms. Effectively, one would have to push copying down to https://github.com/matplotlib/matplotlib/blob/v3.11.1/lib/matplotlib/axis.py#L2309. But there unit conversion may or may not produce a new array. While we could change that to always make a copy, the result is passed in FixedLocator. But FixedLocator can also be used as public API directly, so that it itself would need to do a copy to defend against post-hoc modification. This means we need to do multiple unnecessary copies.
Overall, I would say, that the behavior is explicitly not defined. You should not use modify ticks through this mechanism, but we also don't guarantee that objects are decoupled. williamlus commented on Sep 8, 2026 Sorry for bothering you with this! To be completely honest, I started out working in production, but later found software testing and bug hunting really fascinating, so I built a tool to help discover potential edge cases like this one.
I shared it because I found the behavior quite interesting—modifying the array after passing it to the first subplot implicitly alters the tick locations for both subplots. Here is the complete minimal code snippet to demonstrate the behavior. In this case you still need to manually make a copy of the theta array for the second plot (for example, theta = theta + np.pi * 2) before modifying it.
import numpy as np
import matplotlib.pyplot as plt
attributes = ['Speed', 'Reliability', 'Comfort', 'Safety', 'Efficiency']
theta = np.linspace(0, 2*np.pi, len(attributes), endpoint=False)
fig = plt.figure(figsize=(8, 6))
ax1 = fig.add_subplot(2, 1, 1, projection='polar')
ax1.set_xticks(theta)
ax1.set_xticklabels(attributes)
theta += np.pi * 2
ax2 = fig.add_subplot(2, 1, 2, projection='polar')
ax2.set_thetamin(360)
ax2.set_thetamax(720)
ax2.set_xticks(theta)
ax2.set_xticklabels(attributes)
plt.show()
 Rudra-G-23 commented on Sep 19, 2026 Hi, I’m interested in investigating this issue. I read the discussion here and the closed #32367, and my understanding is that simply copying inside FixedLocator is not sufficient because the broader question is whether Matplotlib should guarantee isolation from mutations of caller-provided arrays.
Before implementing anything, would you prefer this behavior to remain undefined, or is there an API boundary where you would consider copying the input appropriate? If a copy/isolation guarantee is desired, I’d be happy to trace the set_ticks/unit-conversion/FixedLocator paths and add tests for the agreed behavior.
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|