{"record":{"id":"bc76475a8742cf1d","repo":"LorisYounger/VPet","slug":"fdat-found-before-fctl","errorCode":null,"errorMessage":"fdAT found before fcTL.","messagePattern":"fdAT found before fcTL\\.","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"VPet-Simulator.Core/Graph/APNGAnimation.cs","lineNumber":309,"sourceCode":"                            currentFrame = new ApngFrameData\n                            {\n                                Width = result.CanvasWidth,\n                                Height = result.CanvasHeight,\n                                XOffset = 0,\n                                YOffset = 0,\n                                DelayNum = 1,\n                                DelayDen = 10,\n                                DisposeOp = 0,\n                                BlendOp = 0,\n                            };\n                            result.Frames.Add(currentFrame);\n                        }\n                        currentFrame.ImageDataChunks.Add(data);\n                        break;\n                    case \"fdAT\":\n                        imageDataStarted = true;\n                        if (currentFrame == null)\n                            throw new InvalidDataException(\"fdAT found before fcTL.\");\n                        if (data.Length < 4)\n                            throw new InvalidDataException(\"Invalid fdAT chunk.\");\n                        byte[] idatData = new byte[data.Length - 4];\n                        Buffer.BlockCopy(data, 4, idatData, 0, idatData.Length);\n                        currentFrame.ImageDataChunks.Add(idatData);\n                        break;\n                    case \"IEND\":\n                        return result;\n                    default:\n                        if (!imageDataStarted)\n                        {\n                            result.SharedChunks.Add(new PngChunk { Type = type, Data = data });\n                        }\n                        break;\n                }\n            }\n\n            return result;","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/LorisYounger/VPet/blob/ffb9cc2a856244a0f91aa5ecf10d097bcdd4954f/VPet-Simulator.Core/Graph/APNGAnimation.cs#L291-L327","documentation":"APNG requires every fdAT (frame data) chunk to be preceded by an fcTL chunk defining the frame. ParseApng throws when fdAT arrives while currentFrame is null, i.e. no frame control chunk was seen first.","triggerScenarios":"Loading a file containing fdAT chunks with no preceding fcTL — not a conforming APNG sequence.","commonSituations":"Files assembled by buggy custom encoders; chunks reordered by naive PNG manipulation; corrupted animation streams.","solutions":["Regenerate the APNG so each fdAT sequence is preceded by fcTL (use apngasm/ffmpeg).","Re-download the asset from the original source.","Validate chunk ordering (acTL → fcTL → fdAT... → IEND) before load.","Treat the file as invalid and fall back to a static image handler."],"exampleFix":"// before\n// fdAT appears before any fcTL -> throw\n// after\n// rebuild with correct ordering:\n// ffmpeg -i in.png -plays 0 out_apng.png","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { var anim = new APNGAnimation(path); } catch (InvalidDataException ex) when (ex.Message.Contains(\"fdAT found before fcTL\")) { Log.Error($\"invalid APNG chunk order: {path}\"); UseStaticFallback(path); }","preventionTips":["Never hand-reorder PNG chunks","Regenerate animations from source frames instead of patching binaries","Validate fcTL-before-fdAT ordering in asset CI"],"tags":["png","apng","chunk-order"],"backgroundTag":"invalid-state-transition","analyzedSha":"ffb9cc2a856244a0f91aa5ecf10d097bcdd4954f","analyzedAt":"2026-09-15T21:21:10.398Z","contentChangedAt":"2026-09-15T21:21:10.398Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}