stride3d/stride · error · ArgumentException

and cannot both be empty.

Error message

{assetId} and {objectId} cannot both be empty.

What it means

The AbsoluteId constructor throws this ArgumentException when both the AssetId and the Guid objectId are empty. An AbsoluteId is meant to uniquely identify an object within an asset, so at least one of the two identifiers must be set. This is a fail-fast guard against meaningless identity values.

Solutions

  1. Ensure at least one of assetId or objectId is non-empty before constructing the AbsoluteId
  2. Generate a real objectId via Guid.NewGuid() if the asset id is unknown
  3. Fix the upstream deserialization/initialization path that left both identifiers empty

Example fix

// before
var id = new AbsoluteId(AssetId.Empty, Guid.Empty); // throws
// after
var id = new AbsoluteId(assetId, Guid.NewGuid());
Defensive patterns

Strategy: validation

Validate before calling

if (assetId == AssetId.Empty && objectId == Guid.Empty)
    throw new ArgumentException("At least one of assetId or objectId must be set.");
var id = new AbsoluteId(assetId, objectId);

Prevention

When it happens

Trigger: Calling `new AbsoluteId(AssetId.Empty, Guid.Empty)` — e.g. both identifiers came from uninitialized fields, default(T), or deserialization that produced empty values.

Common situations: Deserializing broken/partial asset data, creating placeholder objects before an asset is loaded, using `default` struct initialization instead of a proper id.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sources/core/Stride.Core.Design/AbsoluteId.cs:24

namespace Stride.Core;

/// <summary>
/// Represents the absolute identifier of an identifiable object in an asset.
/// </summary>
[DataContract("AbsoluteId")]
public readonly struct AbsoluteId : IEquatable<AbsoluteId>
{
    /// <summary>
    /// Initializes a new instance of <see cref="AbsoluteId"/>.
    /// </summary>
    /// <param name="assetId"></param>
    /// <param name="objectId"></param>
    /// <exception cref="ArgumentException"><paramref name="assetId"/> and <paramref name="objectId"/> cannot both be empty.</exception>
    public AbsoluteId(AssetId assetId, Guid objectId)
    {
        if (assetId == AssetId.Empty && objectId == Guid.Empty)
            throw new ArgumentException($"{nameof(assetId)} and {nameof(objectId)} cannot both be empty.");

        AssetId = assetId;
        ObjectId = objectId;
    }

    /// <summary>
    /// The identifier of the containing asset.
    /// </summary>
    public AssetId AssetId { get; }

    /// <summary>
    /// The identifier of the object in the asset.
    /// </summary>
    public Guid ObjectId { get; }

    public static bool operator ==(AbsoluteId left, AbsoluteId right)
    {
        return left.Equals(right);

View on GitHub (pinned to 96fad776d2)