{"record":{"id":"924cd0e049a41b08","repo":"stride3d/stride","slug":"no-upgrader-for-asset-type-0-allow-to-reach-version-1","errorCode":null,"errorMessage":"No upgrader for asset type [{0}] allow to reach version {1}","messagePattern":"No upgrader for asset type \\[(.+?)\\] allow to reach version (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/AssetUpgraderCollection.cs","lineNumber":82,"sourceCode":"    }\n\n    internal void Validate(PackageVersion minVersion)\n    {\n        lock (upgraders)\n        {\n            var version = minVersion;\n            foreach (var upgrader in upgraders)\n            {\n                if (!upgrader.Key.Contains(version))\n                    continue;\n\n                version = upgrader.Key.Target;\n                if (version == currentVersion)\n                    break;\n            }\n\n            if (version != currentVersion)\n                throw new InvalidOperationException(\"No upgrader for asset type [{0}] allow to reach version {1}\".ToFormat(AssetType.Name, currentVersion));\n        }\n    }\n\n    public IAssetUpgrader GetUpgrader(PackageVersion initialVersion, out PackageVersion targetVersion)\n    {\n        lock (upgraders)\n        {\n            var upgrader = upgraders.FirstOrDefault(x => x.Key.Contains(initialVersion));\n            if (upgrader.Value == null)\n                throw new InvalidOperationException(\"No upgrader found for version {0} of asset type [{1}]\".ToFormat(currentVersion, AssetType.Name));\n            targetVersion = upgrader.Key.Target;\n\n            if (!instances.TryGetValue(upgrader.Value, out var result))\n            {\n                // Cache the upgrader instances\n                result = (IAssetUpgrader)Activator.CreateInstance(upgrader.Value)!;\n                instances.Add(upgrader.Value, result);\n            }","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/AssetUpgraderCollection.cs#L64-L100","documentation":"AssetUpgraderCollection.Validate walks the registered upgrader ranges from the earliest version, repeatedly advancing to the highest reachable Target, and verifies the chain terminates exactly at currentVersion. If the chain of upgraders for this asset type cannot reach the current version (a gap in the version graph), it throws InvalidOperationException reporting the asset type and the version that could not be reached.","triggerScenarios":"Loading/validating a package whose asset type has upgraders registered with a gap, e.g. ranges (1.0→2.0) and (3.0→4.0) with nothing covering 2.0→3.0, so the iteration stops before currentVersion and version != currentVersion.","commonSituations":"Removing an upgrader for an intermediate asset version that older assets still need; a broken upgrade chain after version bumps where consecutive upgraders' ranges don't abut; plugin/assembly providing an upgrader for the missing range not loaded.","solutions":["Add (or restore) an upgrader covering the missing range so the chain reaches currentVersion.","Fix start/target boundaries of existing upgraders so consecutive ranges connect without gaps.","Ensure the assembly/attribute declaring the missing upgrader is actually registered/loaded.","If the asset no longer supports old versions, remove the asset type or reject old assets instead of pretending a chain exists."],"exampleFix":"// before (gap)\nRegisterUpgrader(typeof(U1), v(1,0,0,0), v(2,0,0,0));\nRegisterUpgrader(typeof(U2), v(3,0,0,0), v(4,0,0,0));\n// after\nRegisterUpgrader(typeof(U1), v(1,0,0,0), v(2,0,0,0));\nRegisterUpgrader(typeof(U1b), v(2,0,0,0), v(3,0,0,0)); // closes the gap\nRegisterUpgrader(typeof(U2), v(3,0,0,0), v(4,0,0,0));","handlingStrategy":"validation","validationCode":"// After registration, Validate() itself is the guard; call it at startup\ncollection.Validate(); // throws early if the upgrade chain has gaps","typeGuard":"static bool ChainReachesCurrent(IEnumerable<VersionRange> ranges, PackageVersion current)\n{\n    var v = ranges.Min(r => r.Start);\n    foreach (var r in ranges.OrderBy(r => r.Start))\n        if (r.Contains(v)) v = r.Target;\n    return v == current;\n}","tryCatchPattern":"try\n{\n    collection.Validate();\n}\ncatch (InvalidOperationException ex)\n{\n    logger.Error($\"Upgrade chain incomplete: {ex.Message}. Register the missing upgrader range.\");\n}","preventionTips":["Never delete an upgrader for an old version while older assets may still exist.","Run Validate() in unit tests for every asset type's upgrader collection.","Keep each upgrader's start equal to the previous upgrader's target."],"tags":["versioning","asset-upgrade","missing-upgrader","validation"],"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"}