LorisYounger/VPet · error · InvalidDataException

Invalid fcTL chunk.

Error message

Invalid fcTL chunk.

What it means

When ParseApng encounters an fcTL (frame control) chunk whose data is shorter than the required 26 bytes, it throws InvalidDataException. fcTL chunks carry mandatory frame geometry/timing fields, so a short chunk means the APNG is structurally malformed.

Solutions

  1. Rebuild the APNG with apngasm/ffmpeg to regenerate valid fcTL chunks.
  2. Re-download the asset.
  3. Validate the PNG chunk stream (length+CRC per chunk) before loading.
  4. Drop the file if it is not needed as an animation.

Example fix

// before
new APNGAnimation("hand_edited.png"); // short fcTL
// after
// apngasm -o rebuilt.png frames/*.png
new APNGAnimation("rebuilt.png");
Defensive patterns

Strategy: try-catch

Try / catch

try { var anim = new APNGAnimation(path); } catch (InvalidDataException ex) when (ex.Message.Contains("fcTL")) { Log.Error($"malformed APNG: {path}"); LoadFallbackGraph(); }

Prevention

When it happens

Trigger: Loading an APNG whose fcTL chunk length field is wrong or truncated so fewer than 26 data bytes are available.

Common situations: Corrupt downloads; hand-edited or hand-built APNGs with wrong chunk lengths; files mangled by tools that re-chunk PNG data incorrectly.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of LorisYounger/VPet@ffb9cc2a85 (2026-09-15). Data as JSON: /api/errors/bb17a44ed21d014e. Report an issue: GitHub.

Appendix: source

Thrown at VPet-Simulator.Core/Graph/APNGAnimation.cs:273

            while (stream.Position < stream.Length)
            {
                uint length = ReadUInt32BigEndian(reader);
                string type = Encoding.ASCII.GetString(reader.ReadBytes(4));
                byte[] data = reader.ReadBytes((int)length);
                ReadUInt32BigEndian(reader);

                switch (type)
                {
                    case "IHDR":
                        result.IhdrTemplate = data;
                        result.CanvasWidth = (int)ReadUInt32BigEndian(data, 0);
                        result.CanvasHeight = (int)ReadUInt32BigEndian(data, 4);
                        break;
                    case "acTL":
                        break;
                    case "fcTL":
                        if (data.Length < 26)
                            throw new InvalidDataException("Invalid fcTL chunk.");
                        currentFrame = new ApngFrameData
                        {
                            Width = (int)ReadUInt32BigEndian(data, 4),
                            Height = (int)ReadUInt32BigEndian(data, 8),
                            XOffset = (int)ReadUInt32BigEndian(data, 12),
                            YOffset = (int)ReadUInt32BigEndian(data, 16),
                            DelayNum = ReadUInt16BigEndian(data, 20),
                            DelayDen = ReadUInt16BigEndian(data, 22),
                            DisposeOp = data[24],
                            BlendOp = data[25],
                        };
                        result.Frames.Add(currentFrame);
                        break;
                    case "IDAT":
                        imageDataStarted = true;
                        if (currentFrame == null)
                        {
                            currentFrame = new ApngFrameData

View on GitHub (pinned to ffb9cc2a85)