{"record":{"id":"25e031c2b6454864","repo":"d2phap/ImageGlass","slug":"ige-native-codec-proxy-codecid-threw-during-g","errorCode":null,"errorMessage":"IGE: Native codec '{proxy.CodecId}' threw during GetAnimationInfo of '{metadata.FilePath}'.","messagePattern":"IGE: Native codec '(.+?)' threw during GetAnimationInfo of '(.+?)'\\.","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"source/ImageGlass.Lib/Plugins/NativePluginAnimator.cs","lineNumber":94,"sourceCode":"        var cancelHandle = PluginHostApiTable.RegisterCancellation(token);\n        IGAnimationInfo info = default;\n        var infoOwned = false;\n        try\n        {\n            IGStatus status;\n            try\n            {\n                fixed (char* pPath = metadata.FilePath)\n                {\n                    var pathRef = new IGStringRef { Data = pPath, Length = metadata.FilePath.Length };\n                    status = codecApi->GetAnimationInfo(pathRef, &info, (void*)cancelHandle);\n                }\n            }\n            catch (Exception ex)\n            {\n                proxy.FailureManager.RecordSoftFailure(proxy.Plugin.PluginId,\n                    $\"managed exception during GetAnimationInfo: {ex.Message}\");\n                throw new InvalidDataException(\n                    $\"IGE: Native codec '{proxy.CodecId}' threw during GetAnimationInfo of '{metadata.FilePath}'.\", ex);\n            }\n\n            if (status == IGStatus.Canceled)\n            {\n                token.ThrowIfCancellationRequested();\n            }\n            if (status != IGStatus.OK)\n            {\n                throw new InvalidDataException(\n                    $\"IGE: Native codec '{proxy.CodecId}' returned status {status} for GetAnimationInfo of '{metadata.FilePath}'.\");\n            }\n            infoOwned = true;\n\n            if (info.FrameCount <= 0 || info.Frames == null)\n            {\n                throw new InvalidDataException(\n                    $\"IGE: Native codec '{proxy.CodecId}' reported zero frames for '{metadata.FilePath}'.\");","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/d2phap/ImageGlass/blob/4a3c4feceffc5a8bb5e56ba836509634aaae47a9/source/ImageGlass.Lib/Plugins/NativePluginAnimator.cs#L76-L112","documentation":"Thrown by NativePluginAnimator.Create when the managed call into codecApi->GetAnimationInfo throws an exception crossing the unsafe boundary. Symmetric to error 24 but for the animation-info ABI: the plugin faulted while building the IGAnimationInfo struct. The inner exception is preserved and a soft failure is recorded against the plugin.","triggerScenarios":"Produced inside the try around the GetAnimationInfo native call (NativePluginAnimator.cs:88-93). Triggers when the thunk into the plugin raises — typically an AccessViolation from a bad pointer or an ABI mismatch in the IGAnimationInfo layout.","commonSituations":"ABI mismatch in the IGAnimationInfo struct size/field order between plugin and host; plugin dereferences a null pointer while parsing the file's frame table; plugin built for a different SDK with a different struct layout; corrupt animated file that crashes the plugin's parser.","solutions":["Inspect ex.InnerException (AccessViolation vs managed) and the recorded soft-failure message to classify the fault.","Rebuild the plugin against the exact host SDK so IGAnimationInfo and IGStringRef layouts match.","Verify the plugin DLL architecture matches the host (x64/ARM64).","If the inner exception is AccessViolation on a specific file, report the file to the plugin author as a parser crash."],"exampleFix":"// before\ncatch (Exception ex) {\n    proxy.FailureManager.RecordSoftFailure(proxy.Plugin.PluginId, $\"managed exception during GetAnimationInfo: {ex.Message}\");\n    throw new InvalidDataException($\"IGE: Native codec '{proxy.CodecId}' threw during GetAnimationInfo of '{metadata.FilePath}'.\", ex);\n}\n\n// after — record the stack type so triage can separate ABI faults from plugin logic faults\ncatch (Exception ex) {\n    var kind = ex is AccessViolationException ? \"access-violation\" : ex.GetType().Name;\n    proxy.FailureManager.RecordSoftFailure(proxy.Plugin.PluginId, $\"{kind} during GetAnimationInfo: {ex.Message}\");\n    throw new InvalidDataException($\"IGE: Native codec '{proxy.CodecId}' threw ({kind}) during GetAnimationInfo of '{metadata.FilePath}'.\", ex);\n}","handlingStrategy":"try-catch","validationCode":"// Validate file existence and codec liveness before the ABI call.\nif (!File.Exists(metadata.FilePath)) throw new FileNotFoundException(metadata.FilePath);\nif (!proxy.Plugin.LiveToken.IsAlive) throw new InvalidOperationException(\"Plugin not loaded\");","typeGuard":null,"tryCatchPattern":"try { return NativePluginAnimator.Create(proxy, metadata, token); }\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"threw during GetAnimationInfo\") && ex.InnerException is AccessViolationException)\n{ _failureManager.RecordHardFailure(proxy.Plugin.PluginId); throw; }","preventionTips":["Build plugins against the exact host ABI for IGAnimationInfo and IGStringRef.","Verify plugin and host architectures match.","Capture and log ex.InnerException to separate ABI faults from plugin logic faults.","Quarantine a plugin after repeated access violations in GetAnimationInfo."],"tags":["plugin","codec","native","animation","access-violation"],"backgroundTag":null,"analyzedSha":"4a3c4feceffc5a8bb5e56ba836509634aaae47a9","analyzedAt":"2026-08-13T16:58:15.523Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}