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

  1. Call End() on the first immediate-mode batch before beginning another one.
  2. Use a deferred sort mode (e.g. SpriteSortMode.Deferred or BackToFront) for the second batch — only one Immediate batch is ever needed.
  3. 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

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


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)