{"record":{"id":"b31d3dbbb571ee30","repo":"AvaloniaUI/Avalonia","slug":"this-resource-is-disposed","errorCode":null,"errorMessage":"This resource is disposed","messagePattern":"This resource is disposed","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Rendering/Composition/Drawing/CompositorResourceHelpers.cs","lineNumber":22,"sourceCode":"using Avalonia.Media;\nusing Avalonia.Rendering.Composition.Server;\nusing Avalonia.Utilities;\n\nnamespace Avalonia.Rendering.Composition.Drawing;\n\ninternal class CompositorRefCountableResource<T> where T : SimpleServerObject\n{\n    public T Value { get; private set; }\n    public int RefCount { get; private set; }\n\n    public CompositorRefCountableResource(T value)\n    {\n        Value = value;\n        RefCount = 1;\n    }\n\n    [MethodImpl(MethodImplOptions.NoInlining)]\n    static void ThrowInvalidOperation() => throw new InvalidOperationException(\"This resource is disposed\");\n    \n    public void AddRef()\n    {\n        if (RefCount <= 0)\n            ThrowInvalidOperation();\n        RefCount++;\n    }\n\n    public bool Release(Compositor c)\n    {\n        if (RefCount <= 0)\n            ThrowInvalidOperation();\n        RefCount--;\n        if (RefCount == 0)\n        {\n            c.DisposeOnNextBatch(Value);\n            return true;\n        }","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Rendering/Composition/Drawing/CompositorResourceHelpers.cs#L4-L40","documentation":"CompositorRefCountableResource tracks a per-compositor reference count starting at 1; both AddRef and Release throw InvalidOperationException('This resource is disposed') if RefCount is already <= 0, i.e. the resource was fully released and scheduled for disposal on the next batch.","triggerScenarios":"Calling AddRef or Release on a CompositorRefCountableResource after its ref count already hit zero (double-release, or add-ref after release).","commonSituations":"Unbalanced AddRef/Release pairs in a custom ICompositionRenderResource, double-disposing a shared brush/pen/geometry resource, or releasing a resource on one path while another path still add-refs it after teardown.","solutions":["Ensure every AddRef has a matching Release; audit ref-count symmetry in your ICompositionRenderResource implementation.","Do not touch a resource after it has been released to zero; recreate it via CreateOrAddRef if needed.","Drive add/ref only through CreateOrAddRef / Release helpers so the count stays consistent."],"exampleFix":"// before\nhandle.Release(compositor);\nhandle.Release(compositor); // RefCount already 0 -> throws\n\n// after\nif (handle.Release(compositor))\n    handle = null; // mark released, never touch again","handlingStrategy":"validation","validationCode":"// Avoid double release: stop touching the handle once it reports fully released.\nif (!handle.Release(compositor)) return; // still referenced\nhandle = null; // fully released; do not AddRef/Release again","typeGuard":null,"tryCatchPattern":"try { handle.AddRef(); }\ncatch (InvalidOperationException ex) when (ex.Message == \"This resource is disposed\")\n{ /* resource gone; recreate via CreateOrAddRef */ }","preventionTips":["Keep AddRef/Release strictly paired per resource.","Null out the handle once Release returns true (fully released).","Drive ref counting through CreateOrAddRef / Release helpers only."],"tags":["composition","resource","refcount","disposed"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}