stride3d/stride · error · InvalidOperationException

is already assigned to , it cannot be shared with

Error message

{value} is already assigned to {value.Component}, it cannot be shared with {this}

What it means

A CollidableComponent's Collider property enforces one-to-one ownership: a collider shape instance already assigned to another component (value.Component != null and != this) cannot be shared. Assigning it here would silently move ownership and break the other component, so it throws InvalidOperationException before reassigning.

Solutions

  1. Create a new collider instance for the second component instead of sharing (clone/duplicate the collider).
  2. Detach from the previous owner first: set the other component's Collider to null, then assign here if you truly intend a move.
  3. Fix the code path that reuses the collider reference (e.g. instantiate per-entity in clone logic).

Example fix

// before
entityB.Get<CollidableComponent>().Collider = entityA.Get<CollidableComponent>().Collider; // shared!
// after
entityB.Get<CollidableComponent>().Collider = new SphereCollider(0.5f); // fresh instance
Defensive patterns

Strategy: validation

Validate before calling

if (collider.Component != null && !ReferenceEquals(collider.Component, targetComponent)) {
    throw new InvalidOperationException("Collider already owned by another component; clone it.");
}
targetComponent.Collider = collider;

Try / catch

try { comp.Collider = sharedCollider; } catch (InvalidOperationException) { comp.Collider = CloneCollider(sharedCollider); }

Prevention

When it happens

Trigger: Writing componentA.Collider = componentB.Collider, or reusing a cached ColliderShape instance across two CollidableComponents, while the previous owner still holds it.

Common situations: Cloning entities without cloning their collider assets, sharing prefab/cached colliders for performance, or copy-paste code assigning one entity's collider to another.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/9df271b2a95d75cb. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.BepuPhysics/Stride.BepuPhysics/CollidableComponent.cs:86

    /// <summary>
    /// The collider definition used by this object.
    /// </summary>
    /// <remarks>
    /// Changing this value will reset some of the internal physics state of this body
    /// </remarks>
    [NotNull]
    [Display(category: CategoryCollider, Expand = ExpandRule.Always)]
    public required ICollider Collider
    {
        get
        {
            return _collider;
        }
        set
        {
            if (value.Component != null && ReferenceEquals(value.Component, this) == false)
            {
                throw new InvalidOperationException($"{value} is already assigned to {value.Component}, it cannot be shared with {this}");
            }

            _collider.Component = null;
            _collider = value;
            _collider.Component = this;
            TryUpdateFeatures();
        }
    }

    /// <summary>
    /// The bounce frequency in hz
    /// </summary>
    /// <remarks>
    /// Must be low enough that the simulation can actually represent it.
    /// If the contact is trying to make a bounce happen at 240hz,
    /// but the integrator timestep is only 60hz,
    /// the unrepresentable motion will get damped out and the body won't bounce as much.
    /// <para>Defaults to <c>30</c>.</para>

View on GitHub (pinned to 96fad776d2)