stride3d/stride · error · InvalidOperationException
No upgrader found for version
Error message
No upgrader found for version {0} of asset type [{1}] What it means
GetUpgrader finds the first registered upgrader whose VersionRange contains the asset's initialVersion. If no range contains it (or the entry has no value), it throws InvalidOperationException with the current version and asset type name — meaning the asset is at a version for which no migration path is registered.
Solutions
- Register an upgrader whose range Contains(initialVersion) for this asset type.
- If the asset version is newer than the library supports, upgrade the engine/package rather than the asset.
- Check that the assembly containing the upgraders for this asset type is loaded and registered.
- Inspect registered VersionRanges and confirm initialVersion falls within one of them.
Example fix
// before var upgrader = collection.GetUpgrader(new PackageVersion(1, 0, 0, 0), out var target); // no range contains 1.0.0.0 // after RegisterUpgrader(typeof(LegacyUpgrader), new PackageVersion(0, 9, 0, 0), new PackageVersion(1, 0, 0, 0)); var upgrader = collection.GetUpgrader(new PackageVersion(1, 0, 0, 0), out var target);
Defensive patterns
Strategy: try-catch
Validate before calling
bool canUpgrade = collection != null && TryPeekUpgrader(collection, initialVersion); // guard by checking if any registered range contains initialVersion before calling
Type guard
static bool HasUpgraderFor(AssetUpgraderCollection c, PackageVersion v) =>
typeof(AssetUpgraderCollection).GetProperty("Upgraders", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) is not null && true; // ranges are internal; prefer validation at registration time Try / catch
try
{
var upgrader = collection.GetUpgrader(assetVersion, out var targetVersion);
}
catch (InvalidOperationException)
{
logger.Error($"No migration path from asset version {assetVersion} for this asset type; asset will be skipped or removed.");
} Prevention
- Keep upgraders for all historical asset versions you still intend to load.
- Hand-editing asset version numbers in files is dangerous; only bump via tooling.
- Ensure the assembly containing upgraders is loaded before loading packages.
When it happens
Trigger: Calling GetUpgrader(initialVersion, out targetVersion) with an initialVersion outside all registered ranges: an asset older than the earliest supported version, newer than currentVersion, or inside a gap between ranges.
Common situations: Loading assets saved by a much older Stride/Xenko version whose version predates registered upgraders; asset version exceeds currentVersion after a hand-edited .sdtasy file; upgrader assembly not loaded so its ranges are absent.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Asset of type has been serialized with newer version , but…
- Asset of type should be updated from version to , but no…
- The target version is lower or equal to the start version.
- The upgrader has a target version higher that the current…
- The upgrader overlaps with another upgrader.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/618166cb2498110d.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets/AssetUpgraderCollection.cs:92
continue;
version = upgrader.Key.Target;
if (version == currentVersion)
break;
}
if (version != currentVersion)
throw new InvalidOperationException("No upgrader for asset type [{0}] allow to reach version {1}".ToFormat(AssetType.Name, currentVersion));
}
}
public IAssetUpgrader GetUpgrader(PackageVersion initialVersion, out PackageVersion targetVersion)
{
lock (upgraders)
{
var upgrader = upgraders.FirstOrDefault(x => x.Key.Contains(initialVersion));
if (upgrader.Value == null)
throw new InvalidOperationException("No upgrader found for version {0} of asset type [{1}]".ToFormat(currentVersion, AssetType.Name));
targetVersion = upgrader.Key.Target;
if (!instances.TryGetValue(upgrader.Value, out var result))
{
// Cache the upgrader instances
result = (IAssetUpgrader)Activator.CreateInstance(upgrader.Value)!;
instances.Add(upgrader.Value, result);
}
return result;
}
}
}
View on GitHub (pinned to 96fad776d2)