MonoGame/MonoGame · error · InvalidOperationException

You cannot modify the depth stencil state after it has been

Error message

You cannot modify the depth stencil state after it has been bound to the graphics device!

What it means

Thrown by DepthStencilState.ThrowIfBound when attempting to modify any property of a user-created DepthStencilState after it has been bound to a GraphicsDevice. Post-binding mutation is blocked to prevent managed/native state desynchronization.

Source

Thrown at MonoGame.Framework/Graphics/States/DepthStencilState.cs:425

                _twoSidedStencilMode = value;
            }
        }

        internal void BindToGraphicsDevice(GraphicsDevice device)
        {
            if (_defaultStateObject)
                throw new InvalidOperationException("You cannot bind a default state object.");
            if (GraphicsDevice != null && GraphicsDevice != device)
                throw new InvalidOperationException("This depth stencil state is already bound to a different graphics device.");
            GraphicsDevice = device;
        }

        internal void ThrowIfBound()
        {
            if (_defaultStateObject)
                throw new InvalidOperationException("You cannot modify a default depth stencil state object.");
            if (GraphicsDevice != null)
                throw new InvalidOperationException("You cannot modify the depth stencil state after it has been bound to the graphics device!");
        }

        /// <summary>
        /// Creates a new instance of the DepthStencilState class with default values.
        /// </summary>
        public DepthStencilState ()
		{
            DepthBufferEnable = true;
            DepthBufferWriteEnable = true;
			DepthBufferFunction = CompareFunction.LessEqual;
			StencilEnable = false;
			StencilFunction = CompareFunction.Always;
			StencilPass = StencilOperation.Keep;
			StencilFail = StencilOperation.Keep;
			StencilDepthBufferFail = StencilOperation.Keep;
			TwoSidedStencilMode = false;
			CounterClockwiseStencilFunction = CompareFunction.Always;
			CounterClockwiseStencilFail = StencilOperation.Keep;

View on GitHub (pinned to 1d71bbd0ff)

Solutions

  1. Configure all DepthStencilState properties before assigning to GraphicsDevice.DepthStencilState.
  2. Pre-create multiple DepthStencilState instances for different modes and switch between them per-frame.
  3. Create a new instance when settings must change (be mindful of allocation cost in hot paths).

Example fix

// before
var ds = new DepthStencilState { DepthBufferEnable = true };
GraphicsDevice.DepthStencilState = ds; // binds
ds.StencilEnable = true; // throws - already bound

// after
var ds = new DepthStencilState
{
    DepthBufferEnable = true,
    StencilEnable = true
}; // configure fully before binding
GraphicsDevice.DepthStencilState = ds;
Defensive patterns

Strategy: validation

Validate before calling

// Configure all properties before binding
var ds = new DepthStencilState
{
    DepthBufferEnable = true,
    DepthBufferWriteEnable = false,
    StencilEnable = true
};
// Only assign (bind) after all properties are set
GraphicsDevice.DepthStencilState = ds;

Prevention

When it happens

Trigger: Assigning myState to GraphicsDevice.DepthStencilState (triggering binding), then later modifying myState.StencilEnable or any other property. Every setter calls ThrowIfBound(), checking GraphicsDevice != null at DepthStencilState.cs:423-424.

Common situations: Toggling stencil or depth-write per-frame on a shared state object. Setting GraphicsDevice.DepthStencilState early, then adjusting in a later frame. Render-loop code that mutates state objects that were already applied. Refactoring that moved property sets after first use.

Related errors


AI-assisted analysis of MonoGame/MonoGame@1d71bbd0ff (2026-08-13). Data as JSON: /api/errors/a9d140181fca8d4e. Report an issue: GitHub.