stride3d/stride · error · ArgumentException

Unable to find a serializer for the specified asset. No…

Error message

Unable to find a serializer for the specified asset. No asset file extension registered to AssetRegistry

What it means

Save asks AssetRegistry.GetDefaultExtension for the file extension registered for the asset's concrete type; when the type has no registered default extension the library cannot pick a serializer and throws ArgumentException. Every asset type you save must be registered in the AssetRegistry.

Solutions

  1. Register the asset type with AssetRegistry so GetDefaultExtension returns an extension (via an AssetDescription / module registration)
  2. Verify the asset's concrete type derives from Asset and its assembly is loaded
  3. Ensure the default extension registered for the type also has a matching serializer (otherwise error 52 follows)
  4. Log asset.GetType() before Save to confirm the type being saved

Example fix

// before
AssetFileSerializer.Save(stream, new MyCustomAsset()); // unregistered type
// after
// in module/plugin init:
AssetRegistry.RegisterFormat(new FileExtensionAssetDescription { AssetType = typeof(MyCustomAsset), FileExtension = ".myasset" });
AssetFileSerializer.Save(stream, new MyCustomAsset());
Defensive patterns

Strategy: validation

Validate before calling

if (asset == null) return;
var ext = AssetRegistry.GetDefaultExtension(asset.GetType());
if (ext == null) throw new ArgumentException($"{asset.GetType()} has no registered default extension");

Type guard

static bool IsRegisteredAsset(object a) => a is Asset && AssetRegistry.GetDefaultExtension(a.GetType()) != null;

Try / catch

try { AssetFileSerializer.Save(stream, asset, yamlMetadata, log); }
catch (ArgumentException ex) when (ex.Message.Contains("No asset file extension registered"))
{ log.Error($"Asset type {asset.GetType()} is not registered"); }

Prevention

When it happens

Trigger: Calling AssetFileSerializer.Save with an object whose runtime type was never registered via an AssetUpgrader/Asset registration (no AssetDescription/extension mapping), e.g. a custom Asset subclass without registration, or a plain object mistaken for an asset.

Common situations: Creating a new custom Asset class and forgetting to register it with the asset registry/plugin; saving a base Asset instance; assembly containing the asset type not loaded at save time.

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/80b8c2a09e5329a9. Report an issue: GitHub.

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/AssetFileSerializer.cs:150

    /// <summary>
    /// Serializes an <see cref="Asset" /> to the specified stream.
    /// </summary>
    /// <param name="stream">The stream.</param>
    /// <param name="asset">The asset object.</param>
    /// <param name="yamlMetadata"></param>
    /// <param name="log">The logger.</param>
    /// <exception cref="System.ArgumentNullException">
    /// stream
    /// or
    /// assetFileExtension
    /// </exception>
    public static void Save(Stream stream, object asset, AttachedYamlAssetMetadata? yamlMetadata, ILogger? log = null, string? assetNamespace = null)
    {
        ArgumentNullException.ThrowIfNull(stream);
        if (asset == null) return;

        var assetFileExtension = AssetRegistry.GetDefaultExtension(asset.GetType())
            ?? throw new ArgumentException("Unable to find a serializer for the specified asset. No asset file extension registered to AssetRegistry");
        var serializer = FindSerializer(assetFileExtension)
            ?? throw new InvalidOperationException($"Unable to find a serializer for [{assetFileExtension}]");
        serializer.Save(stream, asset, yamlMetadata, log, assetNamespace);
    }
}

View on GitHub (pinned to 96fad776d2)