matplotlib/matplotlib · warning
Can not start iterating the frames for the initial draw. Thi
Error message
Can not start iterating the frames for the initial draw. This can be caused by passing in a 0 length sequence for *frames*. If you passed *frames* as a generator it may be exhausted due to a previous display or save.
What it means
FuncAnimation._init_draw, when no init_func was given, draws the initial frame by calling next() on a freshly created frame sequence. If frames was an empty sequence, or a generator that a previous save()/display already consumed, StopIteration is caught and this UserWarning is emitted - the animation is left without initial artists. Generators are single-pass, so reusing one animation for a second save/display is the usual culprit.
Source
Thrown at lib/matplotlib/animation.py:1777
pass
return gen()
else:
return itertools.islice(self.new_frame_seq(), self._save_count)
def _init_draw(self):
super()._init_draw()
# Initialize the drawing either using the given init_func or by
# calling the draw function with the first item of the frame sequence.
# For blitting, the init_func should return a sequence of modified
# artists.
if self._init_func is None:
try:
frame_data = next(self.new_frame_seq())
except StopIteration:
# we can't start the iteration, it may have already been
# exhausted by a previous save or just be 0 length.
# warn and bail.
warnings.warn(
"Can not start iterating the frames for the initial draw. "
"This can be caused by passing in a 0 length sequence "
"for *frames*.\n\n"
"If you passed *frames* as a generator "
"it may be exhausted due to a previous display or save."
)
return
self._draw_frame(frame_data)
else:
self._drawn_artists = self._init_func()
if self._blit:
if self._drawn_artists is None:
raise RuntimeError('When blit=True, the init_func must '
'return a sequence of Artist objects.')
for a in self._drawn_artists:
a.set_animated(self._blit)
self._save_seq.clear()
View on GitHub (pinned to b379c1b69e)
Solutions
- Pass a re-iterable frames: a list (frames=list(gen)), tuple, range, or plain integer count.
- Pass a callable returning a fresh iterator each time: frames=lambda: gen_factory() (frames may be any callable taking no args).
- Alternatively, create a new FuncAnimation for each output, or supply init_func so the initial draw consumes no frame.
Example fix
# before
frames = (f(i) for i in data) # generator, single pass
anim = FuncAnimation(fig, update, frames=frames)
anim.save('a.mp4')
anim.save('b.mp4') # exhausted -> warning
# after
anim = FuncAnimation(fig, update, frames=list(data)) # re-iterable
anim.save('a.mp4')
anim.save('b.mp4') Defensive patterns
Strategy: validation
Validate before calling
def reusable_frames(frames):
if callable(frames):
return frames # re-invoked per iteration
if iter(frames) is iter(frames): # single-pass iterator/generator
return list(frames) # materialize once
return frames # list/tuple/range are re-iterable Prevention
- Never pass bare generators as frames; use lists, tuples, ranges, ints, or zero-arg callables.
- Plan one animation per output, or make frames re-iterable before the first save.
- Provide init_func when you want the initial draw not to depend on the frame sequence.
When it happens
Trigger: frames=gen followed by anim.save('a.mp4') then anim.save('b.mp4') (the generator is exhausted by the first save); frames=[] or another empty sequence; passing an already-consumed iterator object.
Common situations: Saving the same animation twice (e.g. mp4 and gif); interactive display followed by a save; building frames lazily to save memory and forgetting iterators are one-shot.
Related errors
- Animation was deleted without rendering anything. This is mo
- When blit=True, the init_func must return a sequence of Arti
- copy_from_bbox only works when rendering to an ImageSurface
- Invalid bbox
- restore_region only works when rendering to an ImageSurface
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/432156faa5c2c2a9.
Report an issue: GitHub.