Here is a bit more detail and a simple example.
The example below places red squares in an axes. When the user clicks on an existing red square - another square is created and added. When the user hits any key a square is deleted from the axes. The error is triggered by clicking on the red square and then hitting any key, and then clicking a red square again.
By monitoring cbook.py line 235 and cbook.py line 263 it can be seen that after the second mouse click (following one of the squares being deleted), that the process() function builds a loop and begins handling the button press callbacks. Note that there is a dead reference coming later in this list. The first callback involves another square being created and the connect() method being called. In the connect() call - the dead reference is deleted from the callback list. Now upon returning to the process() callback this dead reference is no longer in the callback list and a Key Exception is triggered once it gets to it in the loop.
There are two locations where dead references are cleared from the callback list. When these loops get intermingled - as the case with a callback leading to another connect mid-loop - the exception occurs when both loops attempt to delete the dead reference.
1. Trap the KeyException at the point of attempting to delete it from the list in both places.
2. Place the dead reference check and deletion within a single method ... and perform this check at beginning of the process() and connect() methods before processing callbacks.
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
from matplotlib.pyplot import Figure, Axes, Rectangle
def __init__(self, axes):
self.axes = axes
self.canvas = axes.figure.canvas
self.squares = 
self.last_x = 0
self.last_x += .1
s = Square(self, self.axes, [self.last_x, .4],
.05, .05, facecolor='red', edgecolor='black')
def on_key_press(self, evt):
if len(self.squares) == 0: return
# delete the first square - results in no error
# del self.squares
# delete the last square - results in the error
def __init__(self, manager, axes, *args, **kwds):
Rectangle.__init__(self, *args, **kwds)
self.manager = manager
def selected(self, evt):
within, _ = self.contains(evt)
app = wx.PySimpleApp()
frame = wx.Frame(None)
fig = Figure()
canvas = FigureCanvasWxAgg(frame, -1, fig)
a = Axes(fig, [.1, .1, .8, .8])
sm = SquareManager(a)
# To demonstrate the error:
# 1. click on red sqaure
# 2. press any key
# 3. click on red sqaure again