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
- Register the missing IAdapterSettingsMigration for that (adapterType, FromVersion) in the adapter's service configuration.
- Ship a direct migration from the stored version to the current version.
- 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
- Every adapter version bump must include the migration step
- Startup validation walking the full migration chain
- Keep old migrations until no stored settings can reference them
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
- Settings version is not compatible with adapter ' ' version…
- Adapter ' ' has an invalid settings migration from version…
- OpenID Connect settings must be an object.
- The adapter type ' ' is not installed or deployment-allowed.
- Adapter ' ' settings migration contains a cycle.
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)