{"record":{"id":"eded2eb61245b5a9","repo":"stride3d/stride","slug":"type-0-must-be-assignable-to-asset","errorCode":null,"errorMessage":"Type [{0}] must be assignable to Asset","messagePattern":"Type \\[(.+?)\\] must be assignable to Asset","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/Compiler/AssetCompilerRegistry.cs","lineNumber":103,"sourceCode":"        var typeData = new CompilerTypeData(context, type);\n\n        typeToCompiler[typeData] = compiler;\n    }\n\n    private void UnregisterCompilersFromAssembly(Assembly assembly)\n    {\n        foreach (var typeToRemove in typeToCompiler.Where(typeAndCompile => typeAndCompile.Key.Type.Assembly == assembly || typeAndCompile.Value.GetType().Assembly == assembly).Select(e => e.Key).ToList())\n        {\n            typeToCompiler.Remove(typeToRemove);\n        }\n    }\n\n    private static void AssertAssetType(Type assetType)\n    {\n        ArgumentNullException.ThrowIfNull(assetType);\n\n        if (!typeof(Asset).IsAssignableFrom(assetType))\n            throw new ArgumentException(\"Type [{0}] must be assignable to Asset\".ToFormat(assetType), nameof(assetType));\n    }\n\n    private void AssemblyRegistered(object? sender, AssemblyRegisteredEventArgs e)\n    {\n        // Handle delay-loading assemblies\n        if (e.Categories.Contains(AssemblyCommonCategories.Assets))\n            RegisterAssembly(e.Assembly);\n    }\n\n    private void AssemblyUnregistered(object? sender, AssemblyRegisteredEventArgs e)\n    {\n        if (e.Categories.Contains(AssemblyCommonCategories.Assets))\n            UnregisterAssembly(e.Assembly);\n    }\n\n    private void EnsureTypes()\n    {\n        if (assembliesChanged)","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/Compiler/AssetCompilerRegistry.cs#L85-L121","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the type passed to RegisterCompiler/GetCompiler derives from Stride.Core.Assets.Asset.","Add a generic constraint (where TAsset : Asset) or a runtime check in your registration helper.","Fix typos in reflection-based type lookups so the intended Asset subclass is resolved.","If you meant to register a compilation context or compiler, use the appropriate registry/API instead."],"exampleFix":"// before\nregistry.RegisterCompiler(typeof(MyAssetCompilerContext), compiler); // not an Asset type\n// after\nregistry.RegisterCompiler(typeof(MyAsset), compiler); // MyAsset : Asset","handlingStrategy":"validation","validationCode":"if (assetType == null || !typeof(Asset).IsAssignableFrom(assetType))\n    throw new ArgumentException(\"Type must derive from Asset\", nameof(assetType));\nregistry.RegisterCompiler(assetType, compiler);","typeGuard":"static bool IsAssetType(Type t) => t != null && typeof(Asset).IsAssignableFrom(t);","tryCatchPattern":"try\n{\n    registry.RegisterCompiler(assetType, compiler);\n}\ncatch (ArgumentException ex) when (ex.ParamName == nameof(assetType))\n{\n    logger.Error($\"{assetType} does not derive from Asset: {ex.Message}\");\n}","preventionTips":["Use generic constraints (where TAsset : Asset) on registration helpers.","Do not confuse compiler/context types with asset types; name parameters explicitly.","Unit-test custom compiler registrations at startup."],"tags":["type-mismatch","asset-compilation","argument-validation","registration"],"backgroundTag":"type-mismatch","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}