stride3d/stride · error · ArgumentNullException

ArgumentNullException: deletedObjects

Error message

ArgumentNullException: deletedObjects

What it means

FixReferencesViewModel<T>.Initialize(IEnumerable<T>) throws ArgumentNullException when deletedObjects is null. The method iterates the collection to find referencers of each deleted object, so a null collection cannot be processed.

Solutions

  1. Pass a non-null collection (Enumerable.Empty<T>() when nothing was deleted)
  2. Guard the caller: skip Initialize/dialog when the deleted set is null
  3. Collect deleted objects before invoking the fix-references flow

Example fix

// before
viewModel.Initialize(deletedObjects);
// after
viewModel.Initialize(deletedObjects ?? Enumerable.Empty<AssetViewModel>());
Defensive patterns

Strategy: validation

Validate before calling

if (deletedObjects == null) deletedObjects = Enumerable.Empty<T>();
viewModel.Initialize(deletedObjects);

Type guard

static bool HasDeletedObjects<T>([NotNullWhen(true)] IEnumerable<T>? items) => items != null;

Try / catch

try { viewModel.Initialize(deletedObjects); } catch (ArgumentNullException ex) { logger.LogError(ex, "Initialize requires a collection"); }

Prevention

When it happens

Trigger: Calling Initialize(null) on a FixReferencesViewModel<T> before showing the fix-references dialog.

Common situations: Deleted-asset selection was empty/null when the fix-references flow started (e.g. batch delete with no snapshot of the deleted items).

Related errors


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

Appendix: source

Thrown at sources/editor/Stride.Core.Assets.Editor/Components/FixReferences/FixReferencesViewModel.cs:136

        /// <summary>
        /// Gets a command that indicates to clear the references for the <see cref="CurrentObjectToReplace"/> and
        /// move the next object to fix (or complete the process if the current object is the last one).
        /// </summary>
        public ICommandBase ClearReferencesCommand { get; }

        /// <summary>
        /// Gets a command that indicates to clear the references for the <see cref="CurrentObjectToReplace"/> and
        /// the following object to fix, and complete the process if the current object is the last one.
        /// </summary>
        public ICommandBase ClearAllReferencesCommand { get; }

        /// <summary>
        /// Initializes this view model with the given collection of deleted objects
        /// </summary>
        /// <param name="deletedObjects">The collection of deleted objects for which to fix references.</param>
        public void Initialize(IEnumerable<T> deletedObjects)
        {
            if (deletedObjects == null) throw new ArgumentNullException(nameof(deletedObjects));
            
            foreach (var deletedObject in deletedObjects)
            {
                // ReSharper disable once DoNotCallOverridableMethodsInConstructor - this is intended here
                var referencers = FindReferencers(deletedObject);
                foreach (var referencer in referencers)
                {
                    if (referencer.Value.Count > 0)
                        referencersMap.Add(new ReferenceTarget(deletedObject, referencer.Key), referencer.Value);
                }
            }

            // Go to the first object to fix.
            NextReferenceIssue();
        }

        /// <summary>
        /// Updates the enabled status of the commands.

View on GitHub (pinned to 96fad776d2)