elsa-workflows/elsa-core · error · InvalidOperationException

Adapter ' ' does not provide a settings migration from…

Error message

Adapter '{adapterType}' does not provide a settings migration from version {version}.

What it means

During the forward-migration loop, MigrateAsync looks up a migration registered for (adapterType, version) to step settings toward the adapter's current version. If no migration is registered for the current source version, the chain is broken and this error is thrown rather than silently skipping.

Solutions

  1. Register the missing IAdapterSettingsMigration for that (adapterType, FromVersion) in the adapter's service configuration.
  2. Ship a direct migration from the stored version to the current version.
  3. One-off: manually migrate the stored settings JSON and bump its version.

Example fix

// before
// no migration registered from version 2
// after
services.AddSingleton<IAdapterSettingsMigration>(new MyAdapterSettingsMigration(fromVersion: 2, toVersion: 3, migrate: s => s));
Defensive patterns

Strategy: try-catch

Validate before calling

var current = adapters.Get(type).Describe().SettingsVersion;
for (int v = storedVersion; v < current; v++)
    if (!migrationIndex.ContainsKey((type, v))) throw new InvalidOperationException($"Missing migration step {v} for {type}");

Try / catch

try { await service.MigrateAsync(type, v, settings); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not provide a settings migration"))
{ /* halt migration; ship missing step or manual migration */ }

Prevention

When it happens

Trigger: Settings stored at version N where the adapter registered no IAdapterSettingsMigration with FromVersion == N — e.g. adapter jumped from v1 to v3 and only a 1→3 migration exists, leaving no 2→3 step for settings at v2.

Common situations: Adapter upgrades that skipped registering an intermediate migration step; custom adapters shipped without migration classes; deleting an old migration class too early while old-version settings persist.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/a947ac96656a428c. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.ExternalAuthentication/Services/AdapterSettingsMigrationService.cs:40

        CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();
        if (!adapters.TryGet(adapterType, out var adapter))
            throw new InvalidOperationException($"The adapter type '{adapterType}' is not installed or deployment-allowed.");

        var currentVersion = adapter.Describe().SettingsVersion;
        if (settingsVersion <= 0 || settingsVersion > currentVersion)
            throw new InvalidOperationException($"Settings version {settingsVersion} is not compatible with adapter '{adapterType}' version {currentVersion}.");
        if (settingsVersion == currentVersion)
            return new(currentVersion, settings.Clone(), false);

        var migrated = settings.Clone();
        var version = settingsVersion;
        var stepCount = 0;
        while (version < currentVersion)
        {
            if (!_migrations.TryGetValue((adapterType, version), out var migration))
                throw new InvalidOperationException($"Adapter '{adapterType}' does not provide a settings migration from version {version}.");
            if (migration.ToVersion <= version || migration.ToVersion > currentVersion)
                throw new InvalidOperationException($"Adapter '{adapterType}' has an invalid settings migration from version {version} to {migration.ToVersion}.");
            if (++stepCount > 64)
                throw new InvalidOperationException($"Adapter '{adapterType}' settings migration contains a cycle.");

            migrated = (await migration.MigrateAsync(migrated, cancellationToken)).Clone();
            version = migration.ToVersion;
        }

        return new(version, migrated, true);
    }

    private static IReadOnlyDictionary<(string AdapterType, int FromVersion), IAdapterSettingsMigration> BuildMigrationIndex(
        IEnumerable<IAdapterSettingsMigration> migrations)
    {
        var result = new Dictionary<(string AdapterType, int FromVersion), IAdapterSettingsMigration>();
        foreach (var migration in migrations)
        {

View on GitHub (pinned to fe9217bdfa)