{"record":{"id":"63de09d7c537e3e2","repo":"gohugoio/hugo","slug":"webpanimencoderadd-failed-for-final-frame-n","errorCode":null,"errorMessage":"WebPAnimEncoderAdd failed for final frame\\n","messagePattern":"WebPAnimEncoderAdd failed for final frame\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/warpc/genwebp/webp.c","lineNumber":254,"sourceCode":"            WebPPictureFree(&pic);\n            WebPAnimEncoderDelete(enc);\n            return NULL;\n        }\n\n        if (!WebPAnimEncoderAdd(enc, &pic, timestamp, config))\n        {\n            fprintf(stderr, \"WebPAnimEncoderAdd failed\\n\");\n            WebPPictureFree(&pic);\n            WebPAnimEncoderDelete(enc);\n            return NULL;\n        }\n        timestamp += params.frameDurations[i];\n        WebPPictureFree(&pic);\n    }\n\n    if (!WebPAnimEncoderAdd(enc, NULL, timestamp, config))\n    {\n        fprintf(stderr, \"WebPAnimEncoderAdd failed for final frame\\n\");\n        WebPAnimEncoderDelete(enc);\n        return NULL;\n    }\n\n    WebPData webp_data_out;\n    WebPDataInit(&webp_data_out);\n    if (!WebPAnimEncoderAssemble(enc, &webp_data_out))\n    {\n        fprintf(stderr, \"WebPAnimEncoderAssemble failed\\n\");\n        WebPAnimEncoderDelete(enc);\n        return NULL;\n    }\n    WebPAnimEncoderDelete(enc);\n\n    *output_size = webp_data_out.size;\n    uint8_t *webp_data = malloc(*output_size);\n    if (webp_data == NULL)\n    {","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/internal/warpc/genwebp/webp.c#L236-L272","documentation":"Printed by genwebp's encodeNRGBAAnimated (webp.c:254) when the final flush call WebPAnimEncoderAdd(enc, NULL, timestamp, config) returns false. libwebp uses a NULL picture to signal end-of-animation and to let the encoder finalize internal state; failure here usually indicates the prior frames left the encoder in a bad state, the WebPConfig is internally inconsistent, or memory is exhausted during finalization. The worker deletes the encoder and returns NULL.","triggerScenarios":"The loop completed without error but finalization fails: WebPConfig fields drift between frames (the same config pointer is reused, so this is unlikely unless mutated), an internal encoder state corruption, or memory exhaustion at the finalization step.","commonSituations":"Very large animations where finalization needs to allocate a big consolidated buffer, an earlier WebPAnimEncoderAdd that returned true but left partial state, or a libwebp build with a known finalization bug.","solutions":["Reproduce with the same input on a different libwebp version to rule out a library bug.","Reduce animation size (frame count or canvas) to lower finalization memory pressure.","Rebuild genwebp against a current libwebp release.","Free memory in the worker before finalization (close any held decoder handles).","Fall back to a per-frame static WebP output if animated finalization persistently fails for this input."],"exampleFix":"// before: huge animation finalizes OOM\nenc.Encode(hugeFrames) // WebPAnimEncoderAdd failed for final frame\n\n// after: cap animation size and skip if exceeded\nconst maxAnimPixels = 50_000_000\nif w*h*frameCount > maxAnimPixels {\n    return writeStaticFallback(firstFrame)\n}\nenc.Encode(hugeFrames)","handlingStrategy":"fallback","validationCode":"const maxAnimPixels = 50_000_000\nfunc shouldAnimate(w, h, frames int) bool {\n    return w*h*frames <= maxAnimPixels\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Cap total animation pixel-budget; fall back to static encode when exceeded.","Free upstream decoder handles before finalization to reduce peak memory.","Rebuild genwebp against a current libwebp if finalization fails persistently.","Reproduce the same input on another libwebp version to isolate library bugs."],"tags":["webp","animation","encoding","finalization","oom"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}