stride3d/stride · error · InvalidOperationException

Unable to attach camera [{camera.Entity.Name}] to the graphi

Error message

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.

What it means

Raised by CameraProcessor.AttachCameraToSlot when the camera's slot in the graphics compositor is already occupied by another enabled camera. During Draw, the processor tries to bind the current camera to its slot; if a different enabled camera (slot.Camera) is already attached to that slot, the binding is ambiguous, so an InvalidOperationException naming both entities is thrown instead of silently overriding the existing attachment.

Solutions

  1. Assign each enabled camera a unique Slot from the GraphicsCompositor's camera slots
  2. Disable or detach the other camera occupying the slot before attaching this one
  3. Detach the previous camera via the processor so slot.Camera is null
  4. Audit scene content/prefabs for duplicated camera slot assignments

Example fix

// before
camA.Slot = slot0; camB.Slot = slot0; // conflict
// after
camA.Slot = slot0;
camB.Slot = slot1; // unique slots
Defensive patterns

Strategy: validation

Validate before calling

var slot = compositor.Cameras.FirstOrDefault(s => s.Id == camera.Slot.Id);
if (slot?.Camera != null && slot.Camera != camera) camera.Slot.Id = freeSlotId;

Type guard

bool SlotIsFree(GraphicsCompositor g, CameraComponent c) => g.Cameras.FirstOrDefault(s => s.Id == c.Slot.Id)?.Camera == null;

Try / catch

try { AttachCameraToSlot(compositor, camera); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Another camera")) { /* assign different slot or disable other camera */ }

Prevention

When it happens

Trigger: Attaching a camera whose Slot.Id matches a slot already occupied by another camera component (slot.Camera != null) during the Draw pass.

Common situations: Two entities assigned the same camera slot value; duplicated camera entities from a prefab; forgetting to change camera.Slot when cloning entities; level streaming loading a scene that reuses a slot.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

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

        }

        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)
        {
            if (camera.Slot.AttachedCompositor == null)
                throw new InvalidOperationException($"The camera [{camera.Entity.Name}] isn't attached");

            for (var i = 0; i < camera.Slot.AttachedCompositor.Cameras.Count; ++i)
            {
                var slot = camera.Slot.AttachedCompositor.Cameras[i];
                if (slot.Id == camera.Slot.Id)
                {

View on GitHub (pinned to 96fad776d2)