dotnet/maui · error · InvalidOperationException
Cannot attach Effect to multiple sources
Error message
Cannot attach Effect to multiple sources
What it means
Thrown by Element.AttachEffect when the Effect being attached already has IsAttached == true. An Effect is a single-instance object tied to one element; once attached and its SendAttached called, attempting to attach it to a second element is illegal. This protects against sharing one Effect instance across multiple controls.
Source
Thrown at src/Controls/src/Core/Element/Element.cs:895
{
IReadOnlyList<Element> children = queue.Dequeue().LogicalChildrenInternal;
for (var i = 0; i < children.Count; i++)
{
var child = children[i] as VisualElement;
if (child == null || !child.IsVisible)
continue;
yield return child;
queue.Enqueue(child);
}
}
}
void AttachEffect(Effect effect)
{
if (_effectControlProvider == null)
return;
if (effect.IsAttached)
throw new InvalidOperationException("Cannot attach Effect to multiple sources");
Effect effectToRegister = effect;
if (effect is RoutingEffect re && re.Inner != null)
effectToRegister = re.Inner;
_effectControlProvider.RegisterEffect(effectToRegister);
effectToRegister.Element = this;
effect.SendAttached();
}
void EffectsOnClearing(object sender, EventArgs eventArgs)
{
foreach (Effect effect in _effects)
{
effect?.ClearEffect();
}
}
View on GitHub (pinned to f377ff1c5e)
Solutions
- Create a new Effect instance for each element — instantiate effects per-control rather than sharing.
- If sharing a RoutingEffect, verify re.Inner is null or also clone it.
- In a Replace notification, ensure the old effect is cleared (ClearEffect) before the new one is attached.
Example fix
// before var effect = new MyRoutingEffect(); // shared view1.Effects.Add(effect); view2.Effects.Add(effect); // throws: already attached // after view1.Effects.Add(new MyRoutingEffect()); view2.Effects.Add(new MyRoutingEffect());
Defensive patterns
Strategy: validation
Validate before calling
foreach (var target in targets)
{
if (effect.IsAttached)
effect = CloneEffect(effect); // create a fresh instance
target.Effects.Add(effect);
} Type guard
static bool IsEffectFree(Effect e) => !e.IsAttached;
Try / catch
try { element.Effects.Add(effect); }
catch (InvalidOperationException ex) when (ex.Message == "Cannot attach Effect to multiple sources")
{
element.Effects.Add(CloneEffect(effect)); // attach a fresh instance
} Prevention
- Never share a single Effect instance across multiple elements.
- Create effects per-element (factory or new instance each time).
- When reusing effects from a resource dictionary, clone before attaching.
When it happens
Trigger: Adding the same Effect instance to more than one Element's Effects collection; reusing a single Effect object in multiple elements' Effects lists; adding an already-attached effect during a Replace collection-changed notification.
Common situations: Creating one Effect instance and adding it to multiple controls' Effects collections (a common mistake when factoring effects into shared fields); defining a RoutingEffect once and sharing it across a page's elements; effects loaded from a shared resource dictionary referenced by multiple views.
Related errors
- Implement INativeElementView on cell renderer: {ContentCell.
- No UIViewController found to present.
- You MUST invoke LoadApplication () before calling base.Finis
- call Forms.Init() before this
- InsertPageBefore is not supported globally on iOS, please us
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/dc3f9bef227aa5ea.
Report an issue: GitHub.