gohugoio/hugo · error
WebPPictureImportRGBA failed\n
Error message
WebPPictureImportRGBA failed\n
What it means
Printed inside genwebp's encodeNRGBAAnimated loop (webp.c:235) when WebPPictureImportRGBA fails for a frame. Unlike the static path (826) this print does not include the error_code, but the cause class is the same: stride < width*4, dimensions over WebP's limit, or a frame buffer that is too short. The worker frees the picture, deletes the anim encoder, and returns NULL.
Source
Thrown at internal/warpc/genwebp/webp.c:235
for (int i = 0; i < params.frameCount; i++)
{
WebPPicture pic;
if (!WebPPictureInit(&pic))
{
fprintf(stderr, "WebPPictureInit failed\n");
WebPAnimEncoderDelete(enc);
return NULL;
}
pic.use_argb = 1;
pic.width = params.width;
pic.height = params.height;
const uint8_t *frame_rgba = all_frames_data + i * frame_rgba_size;
if (!WebPPictureImportRGBA(&pic, frame_rgba, params.stride))
{
fprintf(stderr, "WebPPictureImportRGBA failed\n");
WebPPictureFree(&pic);
WebPAnimEncoderDelete(enc);
return NULL;
}
if (!WebPAnimEncoderAdd(enc, &pic, timestamp, config))
{
fprintf(stderr, "WebPAnimEncoderAdd failed\n");
WebPPictureFree(&pic);
WebPAnimEncoderDelete(enc);
return NULL;
}
timestamp += params.frameDurations[i];
WebPPictureFree(&pic);
}
if (!WebPAnimEncoderAdd(enc, NULL, timestamp, config))
{View on GitHub (pinned to 52c9bd7908)
Solutions
- Assert on the Go side that len(all_frames_data) == params.stride*params.height*params.frameCount before invoking the animated encoder.
- Pin params.stride = params.width*4 and verify each decoded frame is laid out at exactly that stride.
- Confirm params.frameCount matches the number of frames actually packed into all_frames_data.
- Compare the canvas dimensions used for decoding against those sent for encoding — they must be identical.
- Re-decode the source if any frame's stride looks inconsistent.
Example fix
// before: stride mismatch between decoder output and encoder params
params.Stride = w * 3 // wrong for RGBA
enc.Encode(params, frames)
// after
params.Stride = w * 4
if len(frames) != params.Stride*h*params.FrameCount {
return fmt.Errorf("frame buffer %d != expected %d", len(frames), params.Stride*h*params.FrameCount)
}
enc.Encode(params, frames) Defensive patterns
Strategy: validation
Validate before calling
func validateAnimFrameBuffer(pix []byte, w, h, stride, frameCount int) error {
if stride != w*4 { return fmt.Errorf("stride %d != width*4 %d", stride, w*4) }
need := stride * h * frameCount
if len(pix) < need { return fmt.Errorf("buffer %d < need %d", len(pix), need) }
return nil
} Prevention
- Pin stride = width*4 for animated RGBA and pass it consistently to decode and encode.
- Verify len(pix) >= stride*height*frameCount before sending.
- Ensure params.frameCount equals the number of frames actually packed into pix.
- Keep canvas dimensions identical between decode and encode.
When it happens
Trigger: params.stride does not equal params.width*4, frame_rgba_size (params.stride*params.height) exceeds the actual remaining bytes in all_frames_data for a given frame index, or width/height drift between frames (the encoder assumes a fixed canvas size).
Common situations: Animated source decoded with a stride that does not match what the Go host sends in params.stride, frame_count mismatch so frame_index*frame_rgba_size runs past the buffer end, or a canvas-size change between decode and encode that was not propagated to params.
Related errors
- WebPPictureImportRGBA failed: %d (%s)\n
- Error creating WebPAnimEncoder\n
- WebPAnimEncoderAdd failed\n
- WebPAnimEncoderAdd failed for final frame\n
- WebPAnimEncoderAssemble failed\n
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/3614e039aff9b2f5.
Report an issue: GitHub.