{"record":{"id":"32f178f5af1ec795","repo":"stride3d/stride","slug":"asset-of-type-assettype-should-be-updated-from-version","errorCode":null,"errorMessage":"Asset of type {assetType} should be updated from version {serializedVersion} to {expectedVersion}, but no asset migration path was found","messagePattern":"Asset of type (.+?) should be updated from version (.+?) to (.+?), but no asset migration path was found","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/AssetMigration.cs","lineNumber":133,"sourceCode":"        }\n\n        if (serializedVersion > expectedVersion)\n        {\n            // Try to open an asset newer than what we support (probably generated by a newer Stride)\n            throw new InvalidOperationException($\"Asset of type {assetType} has been serialized with newer version {serializedVersion}, but only version {expectedVersion} is supported. Was this asset created with a newer version of Stride?\");\n        }\n\n        if (serializedVersion < expectedVersion)\n        {\n            // Perform asset upgrade\n            context.Log.Verbose($\"{Path.GetFullPath(assetFullPath)} needs update, from version {serializedVersion} to version {expectedVersion}\");\n\n            using var yamlAsset = loadAsset.AsYamlAsset();\n            var yamlRootNode = yamlAsset.RootNode;\n\n            // Check if there is any asset updater\n            var assetUpgraders = AssetRegistry.GetAssetUpgraders(assetType, dependencyName)\n                ?? throw new InvalidOperationException($\"Asset of type {assetType} should be updated from version {serializedVersion} to {expectedVersion}, but no asset migration path was found\");\n\n            // Instantiate asset updaters\n            var currentVersion = serializedVersion;\n            while (currentVersion != expectedVersion)\n            {\n                // This will throw an exception if no upgrader is available for the given version, exiting the loop in case of error.\n                var upgrader = assetUpgraders.GetUpgrader(currentVersion, out var targetVersion);\n\n                // Stop if the next version would be higher than what is expected\n                if (untilVersion != null && targetVersion > untilVersion)\n                    break;\n\n                upgrader.Upgrade(context, dependencyName, currentVersion, targetVersion, yamlRootNode, loadAsset);\n                currentVersion = targetVersion;\n            }\n\n            // Make sure asset is updated to latest version\n            PackageVersion? newSerializedVersion = null;","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/AssetMigration.cs#L115-L151","documentation":"Thrown by AssetMigration.MigrateAssetIfNeeded when an asset's serialized version is older than the current expected version, but AssetRegistry.GetAssetUpgraders returns no registered upgrader chain for the asset type. The library refuses to load the asset because it cannot bring the serialized data up to the format the code expects. This is a registration/versioning gap, not data corruption.","triggerScenarios":"Loading (migrating) an asset whose stored version is behind expectedVersion while no AssetUpgraderAttribute/upgrader is registered for that assetType from serializedVersion to expectedVersion (GetAssetUpgraders returns null).","commonSituations":"An asset file was created with an older Stride/plugin version; a custom asset type changed its version but the author forgot to register an upgrader; an assembly defining upgraders is not loaded in the running process.","solutions":["Register an asset upgrader for the type covering the missing version range (AssetUpgraderAttribute or AssetRegistry registration).","If migration is not intended, update the asset file to the current version manually or recreate it.","Ensure the assembly containing the upgrader is referenced and loaded so GetAssetUpgraders finds it."],"exampleFix":"// before: asset still at version 0.1.0, no upgrader\n// after\n[AssetUpgrader(\"MyGame\", \"MyAsset\", \"0.1.0\", \"0.2.0\", typeof(MyAssetUpgrader))]\npublic class MyAsset { ... }","handlingStrategy":"try-catch","validationCode":"if (AssetRegistry.GetAssetUpgraders(assetType, dependencyName) == null)\n    throw new InvalidOperationException($\"No upgrader registered for {assetType} from {serializedVersion} to {expectedVersion}\");","typeGuard":null,"tryCatchPattern":"try { AssetMigration.MigrateAssetIfNeeded(...); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"no asset migration path\")) { log.Error($\"Cannot load asset {assetFullPath}: missing upgrader. {ex.Message}\"); }","preventionTips":["Always add an AssetUpgraderAttribute when bumping an asset type's version.","Keep upgrader version ranges contiguous from the oldest supported version.","Smoke-test loading assets produced by previous releases in CI."],"tags":["assets","migration","versioning"],"backgroundTag":"missing-dependency","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"}