stride3d/stride · error · ArgumentException

Type [ ] must be assignable to Asset

Error message

Type [{0}] must be assignable to Asset

What it means

AssetCompilerRegistry.AssertAssetType validates that any Type used as an asset type (when registering or looking up a compiler) derives from Stride.Core.Assets.Asset, after a null check. Passing a non-Asset type means the registry cannot associate it with asset compilation, so it throws ArgumentException naming assetType.

Solutions

  1. Ensure the type passed to RegisterCompiler/GetCompiler derives from Stride.Core.Assets.Asset.
  2. Add a generic constraint (where TAsset : Asset) or a runtime check in your registration helper.
  3. Fix typos in reflection-based type lookups so the intended Asset subclass is resolved.
  4. If you meant to register a compilation context or compiler, use the appropriate registry/API instead.

Example fix

// before
registry.RegisterCompiler(typeof(MyAssetCompilerContext), compiler); // not an Asset type
// after
registry.RegisterCompiler(typeof(MyAsset), compiler); // MyAsset : Asset
Defensive patterns

Strategy: validation

Validate before calling

if (assetType == null || !typeof(Asset).IsAssignableFrom(assetType))
    throw new ArgumentException("Type must derive from Asset", nameof(assetType));
registry.RegisterCompiler(assetType, compiler);

Type guard

static bool IsAssetType(Type t) => t != null && typeof(Asset).IsAssignableFrom(t);

Try / catch

try
{
    registry.RegisterCompiler(assetType, compiler);
}
catch (ArgumentException ex) when (ex.ParamName == nameof(assetType))
{
    logger.Error($"{assetType} does not derive from Asset: {ex.Message}");
}

Prevention

When it happens

Trigger: Calling RegisterCompiler(typeof(SomeNonAssetType), ...) or GetCompiler(typeof(SomeNonAssetType)) with a type that doesn't inherit Asset; passing an interface, a compile context type, or a typo'd class name resolved via reflection.

Common situations: Confusing ICompilationContext/AssetCompiler types with Asset types when wiring a custom compiler; generic type parameters where the constraint was omitted; reflection-based registration resolving the wrong Type from an assembly string.

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

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/Compiler/AssetCompilerRegistry.cs:103

        var typeData = new CompilerTypeData(context, type);

        typeToCompiler[typeData] = compiler;
    }

    private void UnregisterCompilersFromAssembly(Assembly assembly)
    {
        foreach (var typeToRemove in typeToCompiler.Where(typeAndCompile => typeAndCompile.Key.Type.Assembly == assembly || typeAndCompile.Value.GetType().Assembly == assembly).Select(e => e.Key).ToList())
        {
            typeToCompiler.Remove(typeToRemove);
        }
    }

    private static void AssertAssetType(Type assetType)
    {
        ArgumentNullException.ThrowIfNull(assetType);

        if (!typeof(Asset).IsAssignableFrom(assetType))
            throw new ArgumentException("Type [{0}] must be assignable to Asset".ToFormat(assetType), nameof(assetType));
    }

    private void AssemblyRegistered(object? sender, AssemblyRegisteredEventArgs e)
    {
        // Handle delay-loading assemblies
        if (e.Categories.Contains(AssemblyCommonCategories.Assets))
            RegisterAssembly(e.Assembly);
    }

    private void AssemblyUnregistered(object? sender, AssemblyRegisteredEventArgs e)
    {
        if (e.Categories.Contains(AssemblyCommonCategories.Assets))
            UnregisterAssembly(e.Assembly);
    }

    private void EnsureTypes()
    {
        if (assembliesChanged)

View on GitHub (pinned to 96fad776d2)