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
- Configure all DepthStencilState properties before assigning to GraphicsDevice.DepthStencilState.
- Pre-create multiple DepthStencilState instances for different modes and switch between them per-frame.
- 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
- Set all DepthStencilState properties before assigning to GraphicsDevice.DepthStencilState.
- Pre-create multiple instances for per-frame mode switching.
- Never mutate a state after it has been assigned to the device.
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
- You cannot bind a default state object.
- You cannot modify a default depth stencil state object.
- You cannot modify the blend state after it has been bound to
- This depth stencil state is already bound to a different gra
- You cannot modify the rasterizer state after it has been bou
AI-assisted analysis of MonoGame/MonoGame@1d71bbd0ff (2026-08-13).
Data as JSON: /api/errors/a9d140181fca8d4e.
Report an issue: GitHub.