stride3d/stride · error · ArgumentNullException

ArgumentNullException: templates

Error message

ArgumentNullException: templates

What it means

The AssetTemplatesViewModel(IViewModelServiceProvider, IEnumerable<TemplateAssetDescription>) constructor requires a templates collection and throws ArgumentNullException when it is null. It then wraps each template in a TemplateDescriptionViewModel, sorted by Order.

Solutions

  1. Pass a non-null collection (use Enumerable.Empty<TemplateAssetDescription>() when there are no templates)
  2. Guard the caller: only construct the view model after the template list has loaded
  3. Coalesce null to an empty sequence before constructing

Example fix

// before
new AssetTemplatesViewModel(serviceProvider, loadedTemplates);
// after
new AssetTemplatesViewModel(serviceProvider, loadedTemplates ?? Enumerable.Empty<TemplateAssetDescription>());
Defensive patterns

Strategy: validation

Validate before calling

if (templates == null) templates = Enumerable.Empty<TemplateAssetDescription>();
var vm = new AssetTemplatesViewModel(serviceProvider, templates);

Type guard

static bool HasTemplates([NotNullWhen(true)] IEnumerable<TemplateAssetDescription>? t) => t != null;

Try / catch

try { vm = new AssetTemplatesViewModel(sp, templates); } catch (ArgumentNullException) { vm = new AssetTemplatesViewModel(sp, Enumerable.Empty<TemplateAssetDescription>()); }

Prevention

When it happens

Trigger: Constructing AssetTemplatesViewModel with serviceProvider valid but templates == null.

Common situations: Passing a template list loaded asynchronously that failed to load, or a LINQ result assigned later and left null.

Related errors


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

Appendix: source

Thrown at sources/editor/Stride.Core.Assets.Editor/Components/AddAssets/AssetTemplatesViewModel.cs:20

// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using Stride.Core.Assets.Editor.Components.TemplateDescriptions.ViewModels;
using Stride.Core.Assets.Templates;
using Stride.Core.Annotations;
using Stride.Core.Presentation.ViewModels;

namespace Stride.Core.Assets.Editor.Components.AddAssets
{
    public class AssetTemplatesViewModel : DispatcherViewModel
    {
        private KeyValuePair<TemplateDescriptionViewModel, int> selectedTemplates;

        public AssetTemplatesViewModel([NotNull] IViewModelServiceProvider serviceProvider, [NotNull] IEnumerable<TemplateAssetDescription> templates)
            : base(serviceProvider)
        {
            if (templates == null) throw new ArgumentNullException(nameof(templates));
            var list = templates.Select(x => new KeyValuePair<TemplateDescriptionViewModel, int>(new TemplateDescriptionViewModel(serviceProvider, x), 0)).ToList();
            list.Sort((x, y) => x.Key.Order.CompareTo(y.Key.Order));
            Templates = list;
        }

        public AssetTemplatesViewModel([NotNull] IViewModelServiceProvider serviceProvider, int fileCount, [NotNull] IEnumerable<KeyValuePair<TemplateAssetDescription, int>> templates)
            : base(serviceProvider)
        {
            if (templates == null) throw new ArgumentNullException(nameof(templates));
            FileCount = fileCount;
            var list = templates.Select(x => new KeyValuePair<TemplateDescriptionViewModel, int>(new TemplateDescriptionViewModel(serviceProvider, x.Key), x.Value)).ToList();
            list.Sort((x, y) => x.Key.Order.CompareTo(y.Key.Order));
            Templates = list;
        }

        [NotNull]
        public IEnumerable<KeyValuePair<TemplateDescriptionViewModel, int>> Templates { get; }

View on GitHub (pinned to 96fad776d2)