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

  1. Register an upgrader whose range Contains(initialVersion) for this asset type.
  2. If the asset version is newer than the library supports, upgrade the engine/package rather than the asset.
  3. Check that the assembly containing the upgraders for this asset type is loaded and registered.
  4. 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

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


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)