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
- Rebuild the APNG with apngasm/ffmpeg to regenerate valid fcTL chunks.
- Re-download the asset.
- Validate the PNG chunk stream (length+CRC per chunk) before loading.
- 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
- Generate APNGs only with trusted encoders (apngasm, ffmpeg)
- CRC/length-validate PNG chunks in your asset pipeline
- Hash-verify assets at distribution time
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
- Invalid fdAT chunk.
- fdAT found before fcTL.
- Can not find file
- No APNG frames found.
- Decode APNG frame bitmap failed.
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 ApngFrameDataView on GitHub (pinned to ffb9cc2a85)