stride3d/stride · error · ArgumentNullException

renderCallback

Error message

renderCallback

What it means

Argument-null validation on the renderCallback parameter of WindowsMessageLoop.Run. The message loop invokes this callback every iteration to render a frame; a null callback would crash the loop on its first tick, so Run rejects it up front with ArgumentNullException named 'renderCallback'.

Solutions

  1. Pass a non-null RenderCallback delegate to Run
  2. Ensure the delegate field is assigned before Run is invoked

Example fix

// before
WindowsMessageLoop.Run(form, renderCallback); // renderCallback not assigned
// after
renderCallback = () => RenderFrame();
WindowsMessageLoop.Run(form, renderCallback);
Defensive patterns

Strategy: validation

Validate before calling

if (renderCallback is null) throw new InvalidOperationException("renderCallback must be assigned");
WindowsMessageLoop.Run(form, renderCallback);

Type guard

bool HasCallback(RenderCallback? cb) => cb is not null;

Try / catch

try { WindowsMessageLoop.Run(form, renderCallback); } catch (ArgumentNullException) { /* callback missing; log and abort */ }

Prevention

When it happens

Trigger: Calling Run(form, null) or passing an unset delegate field.

Common situations: Refactoring renamed/removed the render method leaving a null delegate; conditional wiring where the callback is only assigned in some code paths.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/99dc44dbc902695d. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Games/Desktop/WindowsMessageLoop.cs:213

        /// </summary>
        public static void Run(ApplicationContext context, RenderCallback renderCallback)
        {
            Run(context.MainForm, renderCallback);
        }

        /// <summary>
        /// Runs the specified main loop for the specified windows form.
        /// </summary>
        /// <param name="form">The form.</param>
        /// <param name="renderCallback">The rendering callback.</param>
        /// <param name="useApplicationDoEvents">if set to <c>true</c> indicating whether the render loop should use the default <see cref="Application.DoEvents"/> instead of a custom window message loop lightweight for GC. Default is false.</param>
        /// <exception cref="System.ArgumentNullException">form
        /// or
        /// renderCallback</exception>
        public static void Run(Control form, RenderCallback renderCallback, bool useApplicationDoEvents = false)
        {
            if (form == null) throw new ArgumentNullException("form");
            if (renderCallback == null) throw new ArgumentNullException("renderCallback");

            using (var renderLoop = new WindowsMessageLoop(form) { UseApplicationDoEvents = useApplicationDoEvents })
            {
                while (renderLoop.NextFrame())
                {
                    renderCallback();
                }
            }
        }
   }
}
#endif

View on GitHub (pinned to 96fad776d2)