stride3d/stride · error · InvalidOperationException
Only one SpriteBatch at a time can use…
Error message
Only one SpriteBatch at a time can use SpriteSortMode.Immediate
What it means
BatchBase.Begin throws when SpriteSortMode.Immediate is requested while another batch is already in immediate mode (ResourceContext.IsInImmediateMode). Immediate mode renders during Begin, so only one such batch can be active per resource context at a time; a second would interleave draws from an un-Ended batch.
Solutions
- Call End() on the first immediate-mode batch before beginning another one.
- Use a deferred sort mode (e.g. SpriteSortMode.Deferred or BackToFront) for the second batch — only one Immediate batch is ever needed.
- Refactor nested drawing so the inner content is drawn after the outer batch ends, or switch the outer batch to deferred.
Example fix
// before batchA.Begin(GraphicsContext, SpriteSortMode.Immediate); batchB.Begin(GraphicsContext, SpriteSortMode.Immediate); // throws // after batchA.Begin(GraphicsContext, SpriteSortMode.Immediate); batchA.End(); batchB.Begin(GraphicsContext, SpriteSortMode.Immediate);
Defensive patterns
Strategy: validation
Validate before calling
if (sortMode == SpriteSortMode.Immediate && ResourceContext.IsInImmediateMode)
sortMode = SpriteSortMode.Deferred; // downgrade instead of throwing
batch.Begin(context, sortMode); Try / catch
try { batch.Begin(ctx, SpriteSortMode.Immediate); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Immediate"))
{
activeBatch.End();
batch.Begin(ctx, SpriteSortMode.Immediate);
} Prevention
- Track and End the active immediate batch before starting another one.
- Use Deferred sort mode for nested or secondary batches.
- Structure rendering so batches are strictly sequential, never nested.
When it happens
Trigger: Calling Begin(SpriteSortMode.Immediate, ...) on a second SpriteBatch (or SpriteFont batch) before End() was called on the first immediate-mode batch sharing the same graphics resource context.
Common situations: Nested immediate-mode sprite drawing (e.g. drawing UI inside an immediate batch), forgetting End on the first batch, or mixing SpriteBatch and other BatchBase-derived batches both set to Immediate in the same frame.
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
- Cannot end one SpriteBatch while another is using…
- Begin must be called before functionName
- End must be called before functionName
- Aynchronous lock can only be acquired from a micro-thread…
- Trying to enter a lock that has already been entered
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/fde8d2afc83aeec5.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/BatchBase.cs:220
textureUpdater = null;
if (Effect.Effect.HasParameter(TexturingKeys.Texture0))
textureUpdater = Effect.Parameters.GetAccessor(TexturingKeys.Texture0);
if (Effect.Effect.HasParameter(TexturingKeys.TextureCube0))
textureUpdater = Effect.Parameters.GetAccessor(TexturingKeys.TextureCube0);
if (Effect.Effect.HasParameter(TexturingKeys.Texture3D0))
textureUpdater = Effect.Parameters.GetAccessor(TexturingKeys.Texture3D0);
samplerUpdater = null;
if (Effect.Effect.HasParameter(TexturingKeys.Sampler))
samplerUpdater = Effect.Parameters.GetAccessor(TexturingKeys.Sampler);
// Immediate mode, then prepare for rendering here instead of End()
if (sessionSortMode == SpriteSortMode.Immediate)
{
if (ResourceContext.IsInImmediateMode)
{
throw new InvalidOperationException("Only one SpriteBatch at a time can use SpriteSortMode.Immediate");
}
PrepareForRendering();
ResourceContext.IsInImmediateMode = true;
}
// Sets to true isBeginCalled
isBeginCalled = true;
}
protected unsafe virtual void PrepareForRendering()
{
// Use LinearClamp for sampler state
var localSamplerState = samplerState ?? graphicsDevice.SamplerStates.LinearClamp;
// Sets the sampler state of the effect
if (samplerUpdater.HasValue)View on GitHub (pinned to 96fad776d2)