stride3d/stride · error · NotImplementedException

Code upgrade gated at

Error message

Code upgrade gated at {registration.GateVersion} declares resolveSince {resolveSince}, above the project's from-version {item.FromVersion}. Intermediate version-overridden restores (chained boundaries) are not implemented yet; only single-step resolution at the from-version is supported.

What it means

The Roslyn code-upgrade runner only supports single-step resolution at the project's from-version. If a gated upgrade declares ResolveSince above that from-version, resolving it would require an unimplemented intermediate version-overridden restore, so the runner fails loudly with NotImplementedException instead of silently no-oping the rule.

Solutions

  1. Raise the project's from-version (upgrade stepwise) so it is >= the rule's ResolveSince version
  2. Split the upgrade into multiple sequential runs, each within a supported version boundary
  3. Remove or adjust the ResolveSince on the custom upgrade registration if you own the rule
  4. Implement/file support for chained intermediate restores if this scenario must be supported
Defensive patterns

Strategy: validation

Validate before calling

// before running the upgrade, check gate versions against the project's from-version
foreach (var reg in registrations)
    if (reg.ResolveSince is { } rs && rs.Version > item.FromVersion.Version)
        throw new InvalidOperationException($"Rule {reg.GateVersion} needs ResolveSince handling; raise from-version or drop ResolveSince.");

Type guard

static bool IsSingleStepSupported(UpgradeRegistration reg, UpgradeItem item) =>
    !(reg.ResolveSince is { } rs && rs.Version > item.FromVersion.Version);

Try / catch

try
{
    await runner.Run(upgradeItems);
}
catch (NotImplementedException ex) when (ex.Message.Contains("resolveSince"))
{
    logger.Error("Chained boundary upgrade unsupported; adjust from-version or rule: " + ex.Message);
}

Prevention

When it happens

Trigger: Run iterates upgrade registrations; a registration has ResolveSince set to a version strictly greater than item.FromVersion.

Common situations: Running a code upgrade on a project whose from-version is older than the resolver-supported boundary, chained package-family upgrades across multiple version boundaries, upgrading a project pinned to an intermediate old package version.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/ef3c685811589347. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Assets/CodeUpgrade/RoslynCodeUpgradeRunner.cs:53

            var registry = new UpgradeRegistry();
            provider.DeclareUpgrades(registry);

            var applicable = new List<CodeUpgrade>();
            foreach (var registration in registry.CodeUpgrades)
            {
                // Gate: the change landed at GateVersion, so migrate any project coming from below it.
                if (item.FromVersion.Version >= registration.GateVersion.Version)
                    continue;

                // resolveSince is the exact version where the matched OLD form first exists. When it's above
                // the from-version the rule can't bind against the from-version closure; resolving it would
                // need a version-overridden intermediate restore of the package family at that version
                // (sequenced low→high, merging overlapping resolution windows, replaying any family package
                // rename up to it), then a fresh workspace opened there. Not implemented — fail loud rather
                // than silently resolve at the from-version, which would no-op the rule.
                if (registration.ResolveSince is { } resolveSince && resolveSince.Version > item.FromVersion.Version)
                    throw new NotImplementedException(
                        $"Code upgrade gated at {registration.GateVersion} declares resolveSince {resolveSince}, above the " +
                        $"project's from-version {item.FromVersion}. Intermediate version-overridden restores (chained " +
                        $"boundaries) are not implemented yet; only single-step resolution at the from-version is supported.");

                applicable.AddRange(registration.Upgrades);
            }
            if (applicable.Count > 0)
                plans.Add((item, applicable));
        }
        if (plans.Count == 0)
        {
            log.Info($"Code upgrade: {pending.Count} pending project(s), no applicable source migrations.");
            return;
        }

        log.Info($"Code upgrade: applying source migrations to {plans.Count} project(s)...");

        try

View on GitHub (pinned to 96fad776d2)