stride3d/stride · error · InvalidOperationException

Cannot serialize an object of type

Error message

Cannot serialize an object of type {assetPart.GetType().Name} as an asset part reference: the type does not implement {typeof(IIdentifiable).Name}

What it means

IdentifiableAssetPartReference.FillFromPart builds a lightweight reference (id only) from an actual asset part. The part must implement IIdentifiable so its Id can be captured; when it does not, the method throws InvalidOperationException because a reference cannot be formed without an identifier. This is a contract check protecting the serialization pipeline.

Solutions

  1. Make the asset part class implement IIdentifiable (inheriting from the framework's Identifiable base) so it exposes an Id.
  2. Pass the correct part object — the IIdentifiable asset part rather than a plain wrapper — to FillFromPart.
  3. Guard the call with 'assetPart is IIdentifiable' and skip or log parts that cannot be referenced.
  4. If a library type regressed, wrap or adapt it in your own IIdentifiable implementation carrying the id.

Example fix

// before
class MyPart { public Guid Id; ... } // not IIdentifiable
reference.FillFromPart(new MyPart());

// after
class MyPart : Identifiable { ... }
reference.FillFromPart(new MyPart());
Defensive patterns

Strategy: type-guard

Validate before calling

if (assetPart is not IIdentifiable)
    throw new ArgumentException("Asset part must implement IIdentifiable", nameof(assetPart));

Type guard

bool IsReferencablePart(object part) => part is IIdentifiable;

Try / catch

try { reference.FillFromPart(part); }
catch (InvalidOperationException) { log.Warn($"Skipping non-identifiable part {part.GetType().Name}"); }

Prevention

When it happens

Trigger: Calling FillFromPart with an object whose runtime type does not implement IIdentifiable — e.g. passing a plain model/effect object or a custom asset part that forgot to implement IIdentifiable while still being registered as an asset part.

Common situations: Custom asset part types added to an asset without implementing IIdentifiable; API changes between library versions where a part type lost its IIdentifiable implementation; wiring up wrong objects (a wrapper instead of the part) in custom editor tooling.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/Serializers/IdentifiableAssetPartReference.cs:35

    /// Gets or sets the identifier of the asset part represented by this reference.
    /// </summary>
    public Guid Id { get; set; }

    /// <inheritdoc/>
    [DataMemberIgnore]
    public Type InstanceType { get; set; }

    /// <inheritdoc/>
    public override string ToString()
    {
        return $"{{AssetPartReference: {Id}}}";
    }

    /// <inheritdoc/>
    public void FillFromPart(object assetPart)
    {
        if (assetPart is not IIdentifiable identifiable)
            throw new InvalidOperationException($"Cannot serialize an object of type {assetPart.GetType().Name} as an asset part reference: the type does not implement {typeof(IIdentifiable).Name}");

        Id = identifiable?.Id ?? Guid.Empty;
    }

    /// <inheritdoc/>
    public object? GenerateProxyPart(Type partType)
    {
        if (!typeof(IIdentifiable).IsAssignableFrom(partType))
            throw new InvalidOperationException($"Cannot serialize an object of type {partType.Name} as an asset part reference: the type does not implement {typeof(IIdentifiable).Name}");

        if (Id == Guid.Empty)
            return null;

        var assetPart = (IIdentifiable)Activator.CreateInstance(partType)!;
        assetPart.Id = Id;
        return assetPart;
    }
}

View on GitHub (pinned to 96fad776d2)