stride3d/stride · error · InvalidOperationException

The camera [ ] is disabled and can't be attached

Error message

The camera [{camera.Entity.Name}] is disabled and can't be attached

What it means

CameraProcessor.AttachCameraToSlot throws InvalidOperationException when a CameraComponent with Enabled == false is offered for attachment to a GraphicsCompositor camera slot. Stride only allows enabled cameras to occupy compositor slots.

Solutions

  1. Set camera.Enabled = true before the entity is processed / first frame
  2. Only add camera entities to the scene when they should be active
  3. Guard attachment code with if (camera.Enabled) checks
  4. If a camera should be temporarily off, detach it from the slot instead of disabling the component while attached

Example fix

// before
var camera = new CameraComponent { Slot = slotId }; // Enabled defaults false
entity.Add(camera);
// after
var camera = new CameraComponent { Slot = slotId, Enabled = true };
entity.Add(camera);
Defensive patterns

Strategy: validation

Validate before calling

if (!camera.Enabled) camera.Enabled = true; // or skip attaching

Type guard

bool CanAttach(CameraComponent c) => c != null && c.Enabled && c.Slot != null && c.Slot.AttachedCompositor == null;

Try / catch

try { AttachCameraToSlot(compositor, camera); }
catch (InvalidOperationException ex) when (ex.Message.Contains("is disabled")) { /* skip or enable camera */ }

Prevention

When it happens

Trigger: Adding an entity whose CameraComponent.Enabled is false while its camera slot is being resolved during the Draw/processor pass; disabling a camera then forcing re-attachment (e.g. changing Slot or graphics compositor).

Common situations: Scene setup code that adds a camera entity but forgot camera.Enabled = true; spawning prefabs with cameras disabled by default; tooling that toggles camera enabled state before first frame.

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/47a28a60147630b9. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Engine/Engine/Processors/CameraProcessor.cs:131

                    camera.Update();
                }
            }
        }

        protected override void OnEntityComponentRemoved(Entity entity, CameraComponent component, CameraComponent data)
        {
            if (component.Slot.AttachedCompositor != null)
                DetachCameraFromSlot(component);
        }

        private void OnCameraSlotsChanged(object sender, ref FastTrackingCollectionChangedEventArgs e)
        {
            cameraSlotsDirty = true;
        }

        private void AttachCameraToSlot(GraphicsCompositor graphicsCompositor, CameraComponent camera)
        {
            if (!camera.Enabled) throw new InvalidOperationException($"The camera [{camera.Entity.Name}] is disabled and can't be attached");
            if (camera.Slot.AttachedCompositor != null) throw new InvalidOperationException($"The camera [{camera.Entity.Name}] is already attached");

            for (var i = 0; i < graphicsCompositor.Cameras.Count; ++i)
            {
                var slot = graphicsCompositor.Cameras[i];
                if (slot.Id == camera.Slot.Id)
                {
                    if (slot.Camera != null)
                        throw new InvalidOperationException($"Unable to attach camera [{camera.Entity.Name}] to the graphics compositor. Another camera, [{slot.Camera.Entity.Name}], is enabled and already attached to this slot.");

                    slot.Camera = camera;
                    camera.Slot.AttachedCompositor = graphicsCompositor;
                    break;
                }
            }
        }

        private static void DetachCameraFromSlot(CameraComponent camera)

View on GitHub (pinned to 96fad776d2)