anthropics/skills · error · ValueError

No frames to save. Add frames with add_frame() first.

Error message

No frames to save. Add frames with add_frame() first.

What it means

GifBuilder.save() refuses to write a GIF when its internal frames list is empty, because there is nothing to encode. The ValueError tells you to call add_frame() first; it is a straightforward precondition violation, not a resource or encoding failure.

Source

Thrown at skills/slack-gif-creator/core/gif_builder.py:180

        output_path: str | Path,
        num_colors: int = 128,
        optimize_for_emoji: bool = False,
        remove_duplicates: bool = False,
    ) -> dict:
        """
        Save frames as optimized GIF for Slack.

        Args:
            output_path: Where to save the GIF
            num_colors: Number of colors to use (fewer = smaller file)
            optimize_for_emoji: If True, optimize for emoji size (128x128, fewer colors)
            remove_duplicates: If True, remove duplicate consecutive frames (opt-in)

        Returns:
            Dictionary with file info (path, size, dimensions, frame_count)
        """
        if not self.frames:
            raise ValueError("No frames to save. Add frames with add_frame() first.")

        output_path = Path(output_path)

        # Remove duplicate frames to reduce file size
        if remove_duplicates:
            removed = self.deduplicate_frames(threshold=0.9995)
            if removed > 0:
                print(
                    f"  Removed {removed} nearly identical frames (preserved subtle animations)"
                )

        # Optimize for emoji if requested
        if optimize_for_emoji:
            if self.width > 128 or self.height > 128:
                print(
                    f"  Resizing from {self.width}x{self.height} to 128x128 for emoji"
                )
                self.width = 128

View on GitHub (pinned to f6656c1256)

Solutions

  1. Verify frames were added before saving: ensure add_frame() ran at least once
  2. Validate upstream input (e.g. non-empty prompt/text) before starting the build
  3. If frames can legitimately be zero, skip the build entirely instead of calling save()

Example fix

# before
gif.save(out_path)
# after
if not gif.frames:
    raise ValueError("nothing to render: provide text/scenes first")
gif.save(out_path)
Defensive patterns

Strategy: validation

Validate before calling

def builder_has_frames(builder) -> bool:
    return len(getattr(builder, "frames", [])) > 0

Try / catch

try:
    info = builder.save(out)
except ValueError as e:
    if "No frames" in str(e):
        return None  # skip GIF creation for empty input
    raise

Prevention

When it happens

Trigger: Calling save(output_path) on a fresh GifBuilder; calling save() after a deduplicate/reset step removed all frames; a frame-generation loop whose condition never fired (e.g. zero scenes parsed from user input) so add_frame() was never reached.

Common situations: Building a GIF from user-supplied text/emoji where empty input yields zero frames; forgetting that add_frame() must precede save() in the builder pipeline; conditional frame loops (only add on success) where all attempts failed silently.

Related errors


AI-assisted analysis of anthropics/skills@f6656c1256 (2026-08-14). Data as JSON: /api/errors/34551893abc0454e. Report an issue: GitHub.