LorisYounger/VPet · error · InvalidDataException
Decode APNG frame bitmap failed.
Error message
Decode APNG frame bitmap failed.
What it means
During sprite-sheet assembly, DecodeFrameBitmap failed to decode a frame's compressed image data (IDAT/fdAT payload) into an SkiaSharp bitmap, returning null. The loader throws InvalidDataException rather than compositing a corrupt frame.
Solutions
- Re-download or re-export the APNG from a known-good source.
- Validate each frame's data decodes (e.g. SKBitmap.Decode) before shipping the asset.
- Update SkiaSharp to a version supporting the file's color/interlace format.
- Regenerate the animation with apngasm/ffmpeg to rebuild frame chunks.
Example fix
// before
// asset shipped with truncated fdAT; crash at BuildSpriteSheet
// after
// rebuild:
// apngasm -o fixed.png frames/*.png
new APNGAnimation("fixed.png"); Defensive patterns
Strategy: try-catch
Try / catch
try { var anim = new APNGAnimation(path); } catch (InvalidDataException ex) when (ex.Message.Contains("Decode")) { Log.Error($"corrupt frame data in {path}"); LoadFallbackGraph(); } Prevention
- Verify assets with checksums after download
- Always transfer assets in binary mode
- Test-decode all frames with SkiaSharp in asset CI
When it happens
Trigger: BuildSpriteSheet iterates parsed frames and DecodeFrameBitmap returns null for a frame whose zlib/image data is corrupt, truncated, or uses unsupported color formats.
Common situations: Partially downloaded animation files; corrupted fdAT chunks from bad hex edits; APNG variants whose frame data SkiaSharp cannot decode; assets damaged by transfer in text/FTP ASCII mode.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Can not find file
- No APNG frames found.
- Invalid PNG/APNG signature.
- Invalid fcTL chunk.
- fdAT found before fcTL.
AI-assisted analysis of LorisYounger/VPet@ffb9cc2a85 (2026-09-15).
Data as JSON: /api/errors/7ad9f750ca5a87fd.
Report an issue: GitHub.
Appendix: source
Thrown at VPet-Simulator.Core/Graph/APNGAnimation.cs:188
FailMessage = $"--APNGAnimation--{GraphInfo}--\nPath: {Path}\n{e.Message}";
}
}
private void BuildSpriteSheet(ParsedApng parsed)
{
using var canvasBitmap = new SKBitmap(parsed.CanvasWidth, parsed.CanvasHeight, SKColorType.Bgra8888, SKAlphaType.Premul);
using var combinedBitmap = new SKBitmap(FrameWidth * parsed.Frames.Count, FrameHeight, SKColorType.Bgra8888, SKAlphaType.Premul);
using var combinedCanvas = new SKCanvas(combinedBitmap);
canvasBitmap.Erase(SKColors.Transparent);
combinedBitmap.Erase(SKColors.Transparent);
for (int i = 0; i < parsed.Frames.Count; i++)
{
var frameData = parsed.Frames[i];
using var previousCanvas = frameData.DisposeOp == 2 ? canvasBitmap.Copy() : null;
using var patchBitmap = DecodeFrameBitmap(parsed, frameData);
if (patchBitmap == null)
throw new InvalidDataException("Decode APNG frame bitmap failed.");
using (var canvas = new SKCanvas(canvasBitmap))
{
if (frameData.BlendOp == 0)
{
using var clearPaint = new SKPaint { BlendMode = SKBlendMode.Src, Color = SKColors.Transparent };
canvas.DrawRect(new SKRect(frameData.XOffset, frameData.YOffset, frameData.XOffset + frameData.Width, frameData.YOffset + frameData.Height), clearPaint);
}
canvas.DrawBitmap(patchBitmap, frameData.XOffset, frameData.YOffset);
}
SKBitmap drawBitmap = canvasBitmap;
SKBitmap? scaledBitmap = null;
if (canvasBitmap.Width != FrameWidth || canvasBitmap.Height != FrameHeight)
{
scaledBitmap = new SKBitmap(FrameWidth, FrameHeight, canvasBitmap.ColorType, canvasBitmap.AlphaType);
canvasBitmap.ScalePixels(scaledBitmap, SKSamplingOptions.Default);
drawBitmap = scaledBitmap;View on GitHub (pinned to ffb9cc2a85)