stride3d/stride · error · InvalidOperationException

Attempt was made to create a physics constraint, but one of…

Error message

Attempt was made to create a physics constraint, but one of the rigidbodies has not been initialized by the PhysicsProcessor.

What it means

PhysicsConstraintProcessor.Recreate builds the native physics constraint from its description, which requires both referenced rigidbodies to have native counterparts (InternalRigidBody != null). If a rigidbody referenced by BodyA/BodyB has not yet been initialized by the PhysicsProcessor, and skipping uninitialized components is disabled, this InvalidOperationException is thrown.

Solutions

  1. Ensure both referenced rigidbodies are added to entities in a physics-processed scene before the constraint component.
  2. Order component addition so rigidbodies are added/processed before the constraint.
  3. Enable/keep skipUninitializedComponents so constraints with uninitialized bodies are retried on later updates instead of throwing.
  4. Verify BodyA/BodyB assignments point to rigidbodies that actually exist and are enabled.

Example fix

// before
entity.Add(constraintComponent); // may throw if bodies not yet initialized
// after
if (constraintComponent.BodyA?.InternalRigidBody != null &&
    (constraintComponent.BodyB == null || constraintComponent.BodyB.InternalRigidBody != null))
{
    entity.Add(constraintComponent);
}
Defensive patterns

Strategy: validation

Validate before calling

bool ready = constraint.BodyA?.InternalRigidBody != null &&
             (constraint.BodyB == null || constraint.BodyB.InternalRigidBody != null);
if (!ready) return; // defer constraint creation until bodies are initialized

Try / catch

try { entity.Add(constraintComponent); }
catch (InvalidOperationException ex) { /* bodies not yet initialized; retry after physics update */ }

Prevention

When it happens

Trigger: Adding or updating a PhysicsConstraintComponent whose BodyA (or non-null BodyB) is a RigidbodyComponent that has not yet been processed/initialized by the PhysicsProcessor, when Recreate runs from OnEntityComponentAdding or Update with skipUninitializedComponents == false.

Common situations: Adding a constraint and its rigidbodies to an entity at the same time (order not guaranteed); referencing a rigidbody on another entity that is not yet in the scene; loading scenes where constraints are processed before bodies.

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/7329da8a0e0ccecf. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Physics/Engine/PhysicsConstraintProcessor.cs:112

                DisposeOf(component);
            }
            
            if (component.Enabled)
            {
                if (component.Description == null || component.BodyA == null)
                {
                    logger.Warning("ConstraintComponent with an empty description or missing required body. Skipping constraint creation.");
                    return;
                }

                // this can happen when the constraint component is added to the processor
                // before the rigidbodies are added
                if (component.BodyA?.InternalRigidBody == null || component.BodyB != null && component.BodyB.InternalRigidBody == null)
                {
                    if (skipUninitializedComponents)
                        return;
                    else
                        throw new InvalidOperationException("Attempt was made to create a physics constraint, but one of the rigidbodies has not been initialized by the PhysicsProcessor.");
                }

                component.Constraint = component.Description.Build(
                    component.BodyA,
                    component.BodyB);
                component.Simulation = component.BodyA.Simulation;
                component.Simulation.AddConstraint(component.Constraint, component.DisableCollisionsBetweenBodies);
                component.Detached = false;
            }
        }

        private void DisposeOf(PhysicsConstraintComponent component)
        {
            // A disposed constraint will have internal == null
            if (component.Constraint != null && component.Constraint.InternalConstraint != null)
            {
                component.Constraint.Dispose();
            }

View on GitHub (pinned to 96fad776d2)