{"record":{"id":"1ae31a64e86180d7","repo":"AvaloniaUI/Avalonia","slug":"o-gettype-belongs-to-a-different-compositor","errorCode":null,"errorMessage":"{o.GetType()} belongs to a different compositor","messagePattern":"(.+?) belongs to a different compositor","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Rendering/Composition/Drawing/ServerResourceHelperExtensions.cs","lineNumber":55,"sourceCode":"        if (compositor == null)\n            return pen;\n        if (pen == null)\n            return null;\n        if (pen is ImmutablePen immutable)\n            return immutable;\n        if (pen is ICompositionRenderResource<IPen> resource)\n            return resource.GetForCompositor(compositor);\n        ThrowNotCompatible(pen);\n        return null;\n    }\n\n    [MethodImpl(MethodImplOptions.NoInlining), DoesNotReturn]\n    static void ThrowNotCompatible(object o) =>\n        throw new InvalidOperationException(o.GetType() + \" is not compatible with composition\");\n\n    [MethodImpl(MethodImplOptions.NoInlining), DoesNotReturn]\n    static void ThrowForeignCompositor(CompositionObject o) =>\n        throw new InvalidOperationException(o.GetType() + \" belongs to a different compositor\");\n    \n    public static ITransform? GetServer(this ITransform? transform, Compositor? compositor)\n    {\n        if (compositor == null)\n            return transform;\n        if (transform == null)\n            return null;\n        if (transform is ImmutableTransform immutable)\n            return immutable;\n        if (transform is ICompositionRenderResource<ITransform> resource)\n            resource.GetForCompositor(compositor);\n        return new ImmutableTransform(transform.Value);\n    }\n\n    public static IRenderDataGeometry? GetServer(this Geometry? geometry, Compositor? compositor)\n    {\n        if (geometry == null)\n            return null;","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Rendering/Composition/Drawing/ServerResourceHelperExtensions.cs#L37-L73","documentation":"In GetServer for IBrush, when a CompositionBrush is encountered the helper checks that its Compositor matches the drawing compositor; a mismatch calls ThrowForeignCompositor. A composition object's server belongs to its own compositor's render loop and cannot be shared across two compositors/render threads.","triggerScenarios":"Drawing with a CompositionBrush that was created by a different Compositor than the one backing the current RenderDataDrawingContext.","commonSituations":"Sharing a CompositionBrush/visual across multiple top-level windows or surfaces that each have their own Compositor; caching a brush from one compositor and reusing it on another.","solutions":["Create the CompositionBrush on the same Compositor that owns the drawing context.","Per-compositor, recreate shared brushes rather than reusing one across compositors.","Check brush.Compositor == targetCompositor before drawing, and recreate if not."],"exampleFix":"// before\nvar brush = compositorA.CreateColorBrush(color);\n// drawing on a surface backed by compositorB\nctx.DrawRectangle(brush, null, rect); // throws: belongs to a different compositor\n\n// after\nvar brush = compositorB.CreateColorBrush(color);\nctx.DrawRectangle(brush, null, rect);","handlingStrategy":"validation","validationCode":"if (brush is CompositionBrush cb && cb.Compositor != targetCompositor)\n    brush = targetCompositor.CreateColorBrush(/* same color */);\nctx.DrawRectangle(brush, null, rect);","typeGuard":"static bool BelongsTo(CompositionObject o, Compositor c) => o.Compositor == c;","tryCatchPattern":"try { ctx.DrawRectangle(brush, null, rect); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"different compositor\"))\n{ brush = targetCompositor.CreateColorBrush(color); ctx.DrawRectangle(brush, null, rect); }","preventionTips":["Create CompositionBrushes on the same Compositor as the drawing context.","Recreate shared brushes per-compositor instead of reusing one across windows.","Check brush.Compositor == targetCompositor before drawing."],"tags":["composition","compositor","cross-compositor","brush"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}