stride3d/stride · error · ArgumentNullException
Value cannot be null. (Parameter 'canvas')
Error message
Value cannot be null. (Parameter 'canvas')
What it means
The CanvasRenderer constructor requires a non-null Canvas and throws ArgumentNullException(nameof(canvas)) when null. CanvasRenderer wraps a WPF Canvas as the target of drawing commands (IDrawableRenderer); without a canvas nothing can be rendered, so the library fails fast at construction.
Solutions
- Ensure the Canvas is initialized (after InitializeComponent / Loaded) before constructing CanvasRenderer.
- Null-check the canvas at the construction site and defer renderer creation until the canvas is available.
- If the canvas is looked up by name, verify the x:Name matches and the element is in the visual/logical tree.
- Use lazy creation: create the renderer on first draw call, when the canvas is guaranteed to exist.
Example fix
// before
public MyControl()
{
InitializeComponent();
renderer = new CanvasRenderer(canvas); // canvas may be null if lookup failed
}
// after
public MyControl()
{
InitializeComponent();
}
protected override void OnLoaded(EventArgs e)
{
base.OnLoaded(e);
if (canvas == null) throw new InvalidOperationException("Canvas not found.");
renderer = new CanvasRenderer(canvas);
} Defensive patterns
Strategy: validation
Validate before calling
if (canvas == null) throw new InvalidOperationException("Canvas must be resolved before creating CanvasRenderer."); Type guard
static bool CanCreateRenderer(Canvas c) => c is not null;
Try / catch
try { renderer = new CanvasRenderer(canvas); }
catch (ArgumentNullException ex) when (ex.ParamName == "canvas") { log.Error("Canvas was null at renderer creation"); } Prevention
- Create the renderer after InitializeComponent/Loaded, not in constructors.
- Verify x:Name/FindName results before use.
- Lazy-initialize the renderer on first draw.
- In MVVM, wire renderer creation to the view's Loaded event.
When it happens
Trigger: Constructing CanvasRenderer with a null canvas — e.g. a Canvas field/property not yet assigned (XAML not yet loaded), a FindName/FindResource lookup returning null, or passing a null from a factory or data-binding that resolved before the visual tree was built.
Common situations: Instantiating the renderer in a control's constructor before InitializeComponent populated the canvas; code-behind using FindName with a mismatched x:Name; MVVM scenarios where the renderer is created before the view's visual tree exists.
Related errors
- serializerSelector
- registry
- Value cannot be null. (Parameter 'property')
- Value cannot be null. (Parameter 'handler')
- Value cannot be null. (Parameter 'points')
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/55999d2e3672645c.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Drawing/CanvasRenderer.cs:61
namespace Stride.Core.Presentation.Drawing
{
using Color = Stride.Core.Mathematics.Color;
public class CanvasRenderer : IDrawingContext
{
private readonly Dictionary<Color, Brush> cachedBrushes = new Dictionary<Color, Brush>();
private const int MaxPolylinesPerLine = 64;
private const int MinPointsPerPolyline = 16;
/// <summary>
/// The clip rectangle.
/// </summary>
private Rect? clip;
public CanvasRenderer([NotNull] Canvas canvas)
{
if (canvas == null) throw new ArgumentNullException(nameof(canvas));
Canvas = canvas;
UseStreamGeometry = true;
}
/// <summary>
/// Gets or sets the thickness limit for "balanced" line drawing.
/// </summary>
public double BalancedLineDrawingThicknessLimit { get; set; } = 3.5;
[NotNull]
public Canvas Canvas { get; }
/// <summary>
/// Gets or sets a value indicating whether to use stream geometry for lines and polygons rendering.
/// </summary>
/// <value><c>true</c> if stream geometry should be used; otherwise, <c>false</c> .</value>
/// <remarks>Using stream geometry seems to be slightly faster than using path geometry.</remarks>
public bool UseStreamGeometry { get; set; }View on GitHub (pinned to 96fad776d2)