AvaloniaUI/Avalonia · error · InvalidOperationException

This resource doesn't exist on that compositor

Error message

This resource doesn't exist on that compositor

What it means

CompositorResourceHolder.GetForCompositor and Release look up the resource by Compositor in an InlineDictionary; if no entry exists for that compositor, ThrowDoesNotExist fires. A composition render resource is per-compositor: it must be created/add-ref'd on a given compositor before it can be fetched or released there.

Source

Thrown at src/Avalonia.Base/Rendering/Composition/Drawing/CompositorResourceHelpers.cs:84

    }

    public T? TryGetForCompositor(Compositor compositor)
    {
        if (_dictionary.TryGetValue(compositor, out var handle))
            return handle.Value;
        return default;
    }
    
    public T GetForCompositor(Compositor compositor)
    {
        if (_dictionary.TryGetValue(compositor, out var handle))
            return handle.Value;
        ThrowDoesNotExist();
        return default;
    }

    [MethodImpl(MethodImplOptions.NoInlining), DoesNotReturn]
    static void ThrowDoesNotExist() => throw new InvalidOperationException("This resource doesn't exist on that compositor");
    
    public bool Release(Compositor compositor)
    {
        if (!_dictionary.TryGetValue(compositor, out var handle))
            ThrowDoesNotExist();
        if (handle.Release(compositor))
        {
            _dictionary.Remove(compositor);
            return true;
        }

        return false;
    }

    public void ProcessPropertyChangeNotification(AvaloniaPropertyChangedEventArgs change)
    {
        if (change.OldValue is ICompositionRenderResource oldResource)
            TransitiveReleaseAll(oldResource);

View on GitHub (pinned to 11c5427268)

Solutions

  1. Always create/add-ref the resource on a compositor (CreateOrAddRef) before calling GetForCompositor on it.
  2. Use TryGetForCompositor (which returns null instead of throwing) when the compositor association is uncertain.
  3. Ensure each compositor that consumes the resource also releases it symmetrically.

Example fix

// before
var server = resource.GetForCompositor(otherCompositor); // never created here -> throws

// after
resource.CreateOrAddRef(otherCompositor, owner, out var server);
// ... later: resource.Release(otherCompositor);
Defensive patterns

Strategy: validation

Validate before calling

// Use the non-throwing lookup when the compositor association is uncertain.
var server = resource.TryGetForCompositor(compositor);
if (server is null) resource.CreateOrAddRef(compositor, owner, out server);

Type guard

bool ExistsOn(CompositorResourceHolder<T> h, Compositor c) => h.IsAttached && /* per-compositor */ true;

Try / catch

try { return resource.GetForCompositor(c); }
catch (InvalidOperationException ex) when (ex.Message == "This resource doesn't exist on that compositor")
{ resource.CreateOrAddRef(c, owner, out var s); return s; }

Prevention

When it happens

Trigger: Calling GetForCompositor(otherCompositor) or Release(otherCompositor) for a compositor on which the resource was never created via CreateOrAddRef.

Common situations: Sharing one ICompositionRenderResource across windows/surfaces that use different Compositor instances; releasing on the wrong compositor during teardown; reusing a brush created for one compositor with drawing on another.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/46220a4fd2dee596. Report an issue: GitHub.