stride3d/stride · error · InvalidOperationException
Begin must be called before functionName
Error message
Begin must be called before functionName
What it means
BatchBase (the base class of SpriteBatch and UI batch renderers) tracks whether Begin() has been called via the isBeginCalled flag. Methods that draw or flush the batch (End, Draw) call CheckBeginHasBeenCalled and throw if the batch lifecycle was not started. This guards against rendering with an unset effect, viewport, or sampler state that only Begin() configures.
Solutions
- Ensure Begin(...) is called on the batch immediately before any Draw/End calls for that batch instance.
- Check that a previous exception did not abort between Begin and Draw; wrap draw code so state flags stay consistent.
- Verify you are calling Begin/End on the same batch instance, not two different batch objects.
- Do not call End twice; restructure so each Begin is paired with exactly one End.
Example fix
// before spriteBatch.End(); // after spriteBatch.Begin(spriteSortMode, blendState); spriteBatch.Draw(texture, position); spriteBatch.End();
Defensive patterns
Strategy: try-catch
Validate before calling
if (!batchStarted) throw new InvalidOperationException("Call Begin before Draw/End");
// track it yourself:
bool batchStarted = false; Type guard
bool CanDraw(BatchBase b) => b != null && batchStarted;
Try / catch
try { spriteBatch.Draw(...); spriteBatch.End(); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Begin must be called"))
{
log.Warn("SpriteBatch used without Begin");
} Prevention
- Always pair Begin/End adjacent in the same method.
- Use try/finally around End after Begin.
- Keep one batch instance per render phase.
When it happens
Trigger: Calling batch.End(), batch.Draw(...) or batch.Flush without a preceding successful batch.Begin(...); calling End twice after Begin already consumed; an exception thrown inside Begin that skipped its final flag set while the caller continues to Draw/End.
Common situations: Copy-pasted render loops where the Begin call was deleted or commented out; early returns between Begin and End causing a second End on a stale batch object; reusing a batch across frames where the Begin call is in a branch that did not execute (e.g. empty draw list skip logic).
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
- End must be called before functionName
- Only one SpriteBatch at a time can use…
- Cannot end one SpriteBatch while another is using…
- Trying to serialize a Buffer without CPU info.
- Expecting texture input on slot
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/2f84b3951688bfbf.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/BatchBase.cs:271
mutablePipeline.Update();
// Bind pipeline
if (mutablePipeline.State.DepthStencilState.StencilEnable)
GraphicsContext.CommandList.SetStencilReference(stencilReferenceValue);
GraphicsContext.CommandList.SetPipelineState(mutablePipeline.CurrentState);
// Bind VB/IB
if (ResourceContext.VertexBuffer != null)
GraphicsContext.CommandList.SetVertexBuffer(0, ResourceContext.VertexBuffer, 0, vertexStructSize);
if (ResourceContext.IndexBuffer != null)
GraphicsContext.CommandList.SetIndexBuffer(ResourceContext.IndexBuffer, 0, indexStructSize == sizeof(int));
}
protected void CheckBeginHasBeenCalled(string functionName)
{
if (!isBeginCalled)
{
throw new InvalidOperationException("Begin must be called before " + functionName);
}
}
protected void CheckEndHasBeenCalled(string functionName)
{
if (isBeginCalled)
{
throw new InvalidOperationException("End must be called before " + functionName);
}
}
/// <summary>
/// Flushes the sprite batch and restores the device state to how it was before Begin was called.
/// </summary>
public void End()
{
CheckBeginHasBeenCalled("End");
View on GitHub (pinned to 96fad776d2)