stride3d/stride · error · ArgumentNullException
text
Error message
text
What it means
SpriteBatch.DrawString throws ArgumentNullException when the text argument is null (checked via StringProxy.IsNull). An empty string is allowed; only null is rejected, since the renderer cannot iterate a null text buffer. Fail-fast validation at the public entry point.
Solutions
- Pass string.Empty instead of null when there is nothing to render
- Guard: if (text != null) spriteBatch.DrawString(font, text, ...)
- Coalesce at the call site: text ?? string.Empty
- Fix the data source so the bound property is initialized to an empty string
Example fix
// before spriteBatch.DrawString(font, player.Name, pos); // Name may be null // after spriteBatch.DrawString(font, player.Name ?? string.Empty, pos);
Defensive patterns
Strategy: validation
Validate before calling
if (text == null) text = string.Empty; spriteBatch.DrawString(font, text, position);
Type guard
static string SafeText(string s) => s ?? string.Empty;
Try / catch
try { spriteBatch.DrawString(font, text, pos); }
catch (ArgumentNullException) { spriteBatch.DrawString(font, string.Empty, pos); } Prevention
- Initialize text properties to string.Empty, not null
- Never let localization lookups return null — fall back to key or empty string
- Use ?? string.Empty at every DrawString/MeasureString call site
When it happens
Trigger: Passing a C# null string/StringBuilder (or a StringProxy whose internal buffer is null) to any DrawString overload — e.g. building the text from a null result of a lookup or an unset UI property.
Common situations: A UI label bound to a data field that is null until data arrives; concatenation helper returning null on error; deserialized Text property defaulted to null; localization key lookup returning null instead of empty string.
Related errors
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/032865018b5faec2.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/SpriteBatch.cs:488
{
var proxy = new SpriteFont.StringProxy(text);
DrawString(spriteFont, ref proxy, fontSize, ref position, ref color, rotation, ref origin, ref scale, effects, layerDepth, alignment);
}
private void DrawString(SpriteFont spriteFont, ref SpriteFont.StringProxy text, float fontSize, ref Vector2 position, ref Color4 color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth, TextAlignment alignment)
{
DrawString(spriteFont, ref text, fontSize, ref position, ref color, rotation, ref origin, ref scale, effects, layerDepth, alignment);
}
private void DrawString(SpriteFont spriteFont, ref SpriteFont.StringProxy text, float fontSize, ref Vector2 position, ref Color4 color, float rotation, ref Vector2 origin, ref Vector2 scale, SpriteEffects effects, float layerDepth, TextAlignment alignment)
{
if (spriteFont == null)
{
throw new ArgumentNullException("spriteFont");
}
if (text.IsNull)
{
throw new ArgumentNullException("text");
}
if (fontSize < 0)
fontSize = spriteFont.Size;
// calculate the resolution ratio between the screen real size and the virtual resolution
var commandList = GraphicsContext.CommandList;
var viewportSize = commandList.Viewport;
var virtualResolution = GetCurrentResolution(commandList);
var resolutionRatio = new Vector2(viewportSize.Width / virtualResolution.X, viewportSize.Height / virtualResolution.Y);
scale.X = scale.X / resolutionRatio.X;
scale.Y = scale.Y / resolutionRatio.Y;
var fontSize2 = fontSize * ((spriteFont.FontType == SpriteFontType.Dynamic) ? resolutionRatio : Vector2.One);
var drawCommand = new SpriteFont.InternalDrawCommand(this, in fontSize2, in position, in color, rotation, in origin, in scale, effects, layerDepth);
// snap the position the closest 'real' pixel
Vector2.Modulate(ref drawCommand.Position, ref resolutionRatio, out drawCommand.Position);
drawCommand.Position.X = MathF.Round(drawCommand.Position.X);View on GitHub (pinned to 96fad776d2)