{"record":{"id":"6835281fcf6d7d6d","repo":"stride3d/stride","slug":"the-assetupgradertype-must-implement-iassetupgrader","errorCode":null,"errorMessage":"The assetUpgraderType must implement IAssetUpgrader interface","messagePattern":"The assetUpgraderType must implement IAssetUpgrader interface","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/AssetUpgraderAttribute.cs","lineNumber":25,"sourceCode":"/// </summary>\n[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]\npublic class AssetUpgraderAttribute : Attribute\n{\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"AssetUpgraderAttribute\"/> with a range of supported initial version numbers.\n    /// </summary>\n    /// <param name=\"name\">The dependency name.</param>\n    /// <param name=\"startMinVersion\">The minimal initial version number this upgrader can work on.</param>\n    /// <param name=\"targetVersion\">The target version number of this upgrader.</param>\n    /// <param name=\"assetUpgraderType\">The type of upgrader to instantiate to upgrade the asset.</param>\n    public AssetUpgraderAttribute(string name, string startMinVersion, string targetVersion, Type assetUpgraderType)\n    {\n        Name = name;\n        StartVersion = PackageVersion.Parse(startMinVersion);\n        TargetVersion = PackageVersion.Parse(targetVersion);\n\n        if (!typeof(IAssetUpgrader).IsAssignableFrom(assetUpgraderType))\n            throw new ArgumentException(\"The assetUpgraderType must implement IAssetUpgrader interface\", nameof(assetUpgraderType));\n        if (TargetVersion <= StartVersion)\n            throw new ArgumentException(\"The target version is lower or equal to the start version.\", nameof(targetVersion));\n        AssetUpgraderType = assetUpgraderType;\n    }\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"AssetUpgraderAttribute\"/> with a single supported initial version number.\n    /// </summary>\n    /// <param name=\"name\">The dependency name.</param>\n    /// <param name=\"startVersion\">The initial version number this upgrader can work on.</param>\n    /// <param name=\"targetVersion\">The target version number of this upgrader.</param>\n    /// <param name=\"assetUpgraderType\">The type of upgrader to instantiate to upgrade the asset.</param>\n    public AssetUpgraderAttribute(string name, int startVersion, int targetVersion, Type assetUpgraderType)\n        : this(name, \"0.0.\" + startVersion, \"0.0.\" + targetVersion, assetUpgraderType)\n    {\n    }\n\n    /// <summary>","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/AssetUpgraderAttribute.cs#L7-L43","documentation":"The AssetUpgraderAttribute constructor validates that the supplied assetUpgraderType implements IAssetUpgrader and throws ArgumentException otherwise. The attribute's whole purpose is to point migration machinery at an executable upgrader, so a non-implementing type is a construction-time configuration error.","triggerScenarios":"Applying [AssetUpgrader(name, start, target, typeof(SomeClass))] where SomeClass does not implement IAssetUpgrader (or implements the wrong interface).","commonSituations":"Typo/wrong type passed to the attribute; refactoring renamed the interface; author implemented IAssetComparable or a custom method but not IAssetUpgrader.","solutions":["Make the referenced type implement Stride.Core.Assets.IAssetUpgrader (or derive from AssetUpgraderBase).","Fix the typeof(...) argument to point at the actual upgrader class.","Move to the generic AssetUpgraderAttribute<T> form so the compiler enforces the constraint."],"exampleFix":"// before\n[AssetUpgrader(\"Game\", \"Level\", \"1.0.0\", \"1.1.0\", typeof(LevelPatcher))]\npublic class LevelPatcher { }\n// after\npublic class LevelPatcher : AssetUpgraderBase { ... }","handlingStrategy":"type-guard","validationCode":"if (!typeof(IAssetUpgrader).IsAssignableFrom(upgraderType)) throw new ArgumentException($\"{upgraderType} must implement IAssetUpgrader\");","typeGuard":"bool IsUpgraderType(Type t) => typeof(IAssetUpgrader).IsAssignableFrom(t);","tryCatchPattern":"try { var attr = new AssetUpgraderAttribute(name, start, target, upgraderType); } catch (ArgumentException ex) when (ex.Message.Contains(\"IAssetUpgrader\")) { log.Error($\"Bad upgrader type: {upgraderType}\"); }","preventionTips":["Prefer the generic AssetUpgraderAttribute<T> so the compiler enforces the interface.","Keep all upgraders derived from AssetUpgraderBase.","Recheck typeof(...) arguments after interface renames/refactors."],"tags":["assets","attribute","interface"],"backgroundTag":"invalid-argument-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}