gohugoio/hugo · error
WebPAnimEncoderAssemble failed\n
Error message
WebPAnimEncoderAssemble failed\n
What it means
Printed by genwebp's encodeNRGBAAnimated (webp.c:263) when WebPAnimEncoderAssemble returns false. Assemble walks the accumulated frames and produces the final RIFF-formatted WebP byte stream; failure indicates an internal encoder error, typically memory allocation failure while building the container, or an encoder that was left in an invalid state. The worker deletes the encoder and returns NULL.
Source
Thrown at internal/warpc/genwebp/webp.c:263
WebPAnimEncoderDelete(enc);
return NULL;
}
timestamp += params.frameDurations[i];
WebPPictureFree(&pic);
}
if (!WebPAnimEncoderAdd(enc, NULL, timestamp, config))
{
fprintf(stderr, "WebPAnimEncoderAdd failed for final frame\n");
WebPAnimEncoderDelete(enc);
return NULL;
}
WebPData webp_data_out;
WebPDataInit(&webp_data_out);
if (!WebPAnimEncoderAssemble(enc, &webp_data_out))
{
fprintf(stderr, "WebPAnimEncoderAssemble failed\n");
WebPAnimEncoderDelete(enc);
return NULL;
}
WebPAnimEncoderDelete(enc);
*output_size = webp_data_out.size;
uint8_t *webp_data = malloc(*output_size);
if (webp_data == NULL)
{
fprintf(stderr, "malloc failed for final webp data\n");
WebPDataClear(&webp_data_out);
return NULL;
}
memcpy(webp_data, webp_data_out.bytes, *output_size);
WebPDataClear(&webp_data_out);
return webp_data;
}View on GitHub (pinned to 52c9bd7908)
Solutions
- Reduce animation size (fewer frames or smaller canvas) to shrink the assembled output.
- Raise the worker memory limit and watch RSS during assemble with /usr/bin/time -v.
- Rebuild against a current libwebp and re-test the same input.
- If the input is pathological (thousands of tiny frames), pre-coalesce or drop redundant frames before encoding.
- Fall back to a non-animated output format for inputs that consistently fail assemble.
Example fix
# before: 500-frame animation, assemble fails OOM in a 128MB container
$ convert big.gif out.webp
# after: raise worker memory and cap frame count
# docker/compose: mem_limit: 1g
# Hugo side: drop frames beyond a cap before encoding
if frameCount > 200 { frames = frames[:200] } Defensive patterns
Strategy: fallback
Validate before calling
// Cap animated output size; if exceeded, skip animated WebP.
const maxFrames = 200
func maybeTrimFrames(frames []Frame) []Frame {
if len(frames) > maxFrames { return frames[:maxFrames] }
return frames
} Prevention
- Limit frame count and canvas to keep the assembled output within memory.
- Run only one animated encode at a time per worker to bound peak RSS.
- Raise the worker memory limit for known-large inputs.
- Rebuild against a current libwebp to rule out assemble-path bugs.
When it happens
Trigger: All frames added successfully and the flush sentinel succeeded, but assembling the final container failed: OOM while allocating the output WebPData, internal inconsistency in the anim encoder state, or a libwebp version bug in the assemble path.
Common situations: Animations with many frames whose assembled output is very large, low-memory worker containers, or a libwebp build/runtime mismatch that corrupts internal encoder state.
Related errors
- WebPEncode failed: %d (%s)\n
- Error creating WebPAnimEncoder\n
- WebPAnimEncoderAdd failed for final frame\n
- malloc failed for final webp data\n
- WebPPictureInit failed\n
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/011c8d1c1282f59c.
Report an issue: GitHub.