stride3d/stride · error · ArgumentNullException

Value cannot be null. (Parameter 'value')

Error message

Value cannot be null. (Parameter 'value')

What it means

Null-value guard reached via the location handling in the AssetItem constructor chain: a null value (typically the UFile location converted/set through the 'value' parameter) was supplied. The constructor rejects it because an AssetItem cannot have a null location.

Solutions

  1. Compute a valid non-null UFile before assigning Location (e.g. new UFile("/MyGame/AssetName"))
  2. Check that the rename/move input strings are non-empty before applying
  3. Never assign null; remove the item and re-add instead of nulling its location
  4. Guard assignments: only set Location when new value is non-null and non-empty

Example fix

// before
item.Location = newName; // newName is null/empty UFile
// after
if (!UFile.IsNullOrEmpty(newName))
    item.Location = new UFile($"/{package.Name}/{newName}");
Defensive patterns

Strategy: validation

Validate before calling

if (newLocation == null || string.IsNullOrEmpty(newLocation.FullPath))
    throw new InvalidOperationException("New location must be non-empty");
item.Location = newLocation;

Type guard

static bool ValidNewLocation(UFile v) => v != null && !string.IsNullOrWhiteSpace(v.FullPath);

Try / catch

try { item.Location = newLocation; }
catch (ArgumentNullException ex) when (ex.ParamName == "value")
{ log.Error("Cannot set AssetItem.Location to null"); }

Prevention

When it happens

Trigger: Assigning null to AssetItem.Location via code that does e.g. item.Location = someUnsetUFile, or a data-binding/serializer round-trip writing null into the property.

Common situations: Renaming/moving assets in a package session and computing the new URL from an empty string; reflection-driven property copy from a source item whose Location was null; YAML deserialization into a constructed item.

Related errors


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

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/AssetItem.cs:58

    /// <param name="location">The location.</param>
    /// <param name="asset">The asset.</param>
    /// <param name="package">The package.</param>
    /// <exception cref="ArgumentNullException">location</exception>
    /// <exception cref="ArgumentNullException">asset</exception>
    internal AssetItem(UFile location, Asset asset, Package? package)
    {
        this.location = location ?? throw new ArgumentNullException(nameof(location));
        this.asset = asset ?? throw new ArgumentNullException(nameof(asset));
        Package = package;
        isDirty = true;
    }

    /// <summary>
    /// Gets the qualified URL of this asset (rooted under its package's namespace, e.g. /MyGame/Ground).
    /// </summary>
    /// <value>The location.</value>
    [DataMember]
    public UFile Location { get => location; internal set => location = value ?? throw new ArgumentNullException(nameof(value)); }

    /// <summary>
    /// The asset's unqualified URL: its <see cref="Location"/> without the package namespace root
    /// (equal to <see cref="Location"/> for a bare package).
    /// </summary>
    public UFile UnqualifiedUrl => new(AssetNamespaceHelper.Unqualify(Location.FullPath, Package?.Container?.AssetNamespace ?? Package?.AssetNamespace));

    /// <summary>
    /// Gets or sets the real location of this asset if it is overriden (similar to `Link` in C# project files).
    /// </summary>
    public UFile? AlternativePath { get; set; }

    /// <summary>
    /// Gets the directory where the assets will be stored on the disk relative to the <see cref="Package"/>. The directory
    /// will update the list found in <see cref="Package.AssetFolders"/>
    /// </summary>
    /// <value>The directory.</value>
    public UDirectory? SourceFolder { get; set; }

View on GitHub (pinned to 96fad776d2)