stride3d/stride · error · InvalidOperationException
Cannot end one SpriteBatch while another is using…
Error message
Cannot end one SpriteBatch while another is using SpriteSortMode.Immediate
What it means
In SpriteSortMode.Immediate the batch draws sprites directly as they are submitted. If one SpriteBatch is in Immediate mode, ending a second SpriteBatch (with queued draws) would change device state and break the in-flight immediate rendering, so End throws this InvalidOperationException.
Solutions
- Call End() on the Immediate-mode SpriteBatch before ending any other batch with pending draws.
- Restructure rendering so Immediate and deferred batches are not interleaved.
- Switch the immediate batch to a deferred sort mode (e.g. BackToFront) if immediate semantics are not required.
- Ensure End is called on the immediate batch even on early-exit paths (try/finally).
Example fix
// before immediateBatch.Begin(SpriteSortMode.Immediate, blend); deferredBatch.Begin(SpriteSortMode.Deferred, blend); deferredBatch.End(); // throws // after immediateBatch.Begin(SpriteSortMode.Immediate, blend); immediateBatch.End(); deferredBatch.Begin(SpriteSortMode.Deferred, blend); deferredBatch.End();
Defensive patterns
Strategy: validation
Validate before calling
// before ending a deferred batch, ensure no immediate batch is active bool immediateActive = false; // track when Begin(SpriteSortMode.Immediate, ...) is called if (!immediateActive) deferredBatch.End();
Type guard
bool CanEndBatch(BatchBase b) => !immediateBatchActive || ReferenceEquals(b, immediateBatch);
Try / catch
try { deferredBatch.End(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("SpriteSortMode.Immediate"))
{
immediateBatch.End();
deferredBatch.End();
} Prevention
- End immediate-mode batches before other batches.
- Avoid interleaving Immediate and deferred batches.
- Track which batch is in Immediate mode.
When it happens
Trigger: spriteBatchA.Begin(Immediate, ...) is active and batchSizeB.End() is called while spriteBatchB still has queued draws (drawsQueueCount > 0); interleaving an immediate-mode batch with a deferred batch's End without ending the immediate batch first.
Common situations: Mixing an immediate-mode SpriteBatch for per-pixel custom effects with a normal deferred SpriteBatch for text/UI in the same frame; forgetting End on the immediate batch before flushing the other one.
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
- Only one SpriteBatch at a time can use…
- 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/7c2848692543da60.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/BatchBase.cs:299
}
/// <summary>
/// Flushes the sprite batch and restores the device state to how it was before Begin was called.
/// </summary>
public void End()
{
CheckBeginHasBeenCalled("End");
if (sortMode == SpriteSortMode.Immediate)
{
ResourceContext.IsInImmediateMode = false;
}
else if (drawsQueueCount > 0)
{
// Draw the queued sprites now.
if (ResourceContext.IsInImmediateMode)
{
throw new InvalidOperationException("Cannot end one SpriteBatch while another is using SpriteSortMode.Immediate");
}
// If not immediate, then setup and render all sprites
PrepareForRendering();
FlushBatch();
}
ResourceContext = null;
// We are with begin pair
isBeginCalled = false;
}
private void SortSprites()
{
IComparer<int> comparer;
switch (sortMode)View on GitHub (pinned to 96fad776d2)