You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Run the existing frame-position restore in ImageSequence.all_frames() when frame collection raises, as well as when it succeeds.
Add a regression with a custom image that raises during seek(), checking that the exception propagates and the original position is restored.
Previously, an exception while collecting frames left the caller's image at the failed frame. The finally block covers frame collection only; callback execution and successful results keep their existing behavior.
The change is also documented in the 13.0.0 release notes.
Validation on the current head:
python3 selftest.py — 59 passed.
pytest -q Tests/test_imagesequence.py — 9 passed.
Applicable pre-commit hooks for the changed test and release note — passed.
Before the test simplification, the unchanged production fix also passed the full local test suite, repository lint, and mypy.
Hi. I'm curious - is this a theoretical concern, or something that actually caused a problem for you? If nothing else, I want to make sure that individual Pillow formats aren't raising errors during seek() on valid images.
radarhere
changed the title
Restore image position when all_frames copying fails
Restore image position after an error in ImageSequence.all_frames()
Sep 14, 2026
Thanks for asking. This came from inspecting ImageSequence.all_frames(), not from a user report. I reproduced the state leak with Tests/images/multipage.tiff by starting on frame 2 and deliberately raising a pre-created RuntimeError from Image.Image.copy() on frame 1. Before the fix, the image remained on frame 1. I have not observed any Pillow format raising from seek() on a valid image, so I do not have evidence of a spontaneous format-specific seek failure.
Thanks as well for the fork PR. I applied both suggested commits. The custom Image test exercises the same finally cleanup path more simply, and the release-note wording is more accurate for list input because processing stops at the exception and later images are not visited. The current head passes selftest.py, Tests/test_imagesequence.py, and the applicable pre-commit hooks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes proposed in this pull request:
ImageSequence.all_frames()when frame collection raises, as well as when it succeeds.seek(), checking that the exception propagates and the original position is restored.Previously, an exception while collecting frames left the caller's image at the failed frame. The
finallyblock covers frame collection only; callback execution and successful results keep their existing behavior.The change is also documented in the 13.0.0 release notes.
Validation on the current head:
python3 selftest.py— 59 passed.pytest -q Tests/test_imagesequence.py— 9 passed.Before the test simplification, the unchanged production fix also passed the full local test suite, repository lint, and mypy.