{"record":{"id":"c83e2f6d387c1a86","repo":"elsa-workflows/elsa-core","slug":"adapter-migration-adaptertype-registers-more-than-one","errorCode":null,"errorMessage":"Adapter '{migration.AdapterType}' registers more than one migration from version {migration.FromVersion}.","messagePattern":"Adapter '(.+?)' registers more than one migration from version (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.ExternalAuthentication/Services/AdapterSettingsMigrationService.cs","lineNumber":62,"sourceCode":"                throw new InvalidOperationException($\"Adapter '{adapterType}' settings migration contains a cycle.\");\n\n            migrated = (await migration.MigrateAsync(migrated, cancellationToken)).Clone();\n            version = migration.ToVersion;\n        }\n\n        return new(version, migrated, true);\n    }\n\n    private static IReadOnlyDictionary<(string AdapterType, int FromVersion), IAdapterSettingsMigration> BuildMigrationIndex(\n        IEnumerable<IAdapterSettingsMigration> migrations)\n    {\n        var result = new Dictionary<(string AdapterType, int FromVersion), IAdapterSettingsMigration>();\n        foreach (var migration in migrations)\n        {\n            if (string.IsNullOrWhiteSpace(migration.AdapterType) || migration.FromVersion <= 0)\n                throw new InvalidOperationException(\"Adapter settings migrations must define an adapter type and a positive source version.\");\n            if (!result.TryAdd((migration.AdapterType, migration.FromVersion), migration))\n                throw new InvalidOperationException($\"Adapter '{migration.AdapterType}' registers more than one migration from version {migration.FromVersion}.\");\n        }\n        return result;\n    }\n}\n","sourceCodeStart":44,"sourceCodeEnd":67,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.ExternalAuthentication/Services/AdapterSettingsMigrationService.cs#L44-L67","documentation":"BuildMigrationIndex keys migrations by (AdapterType, FromVersion); two migrations claiming the same adapter type and source version are ambiguous, so registration fails fast with this error instead of picking one nondeterministically.","triggerScenarios":"Registering two IAdapterSettingsMigration implementations with identical AdapterType and FromVersion — e.g. an old migration class left in place while a replacement with the same FromVersion was added.","commonSituations":"Copy-pasting a migration class without changing FromVersion; accidentally registering the same migration type twice in DI; merging branches that each added a migration from the same version.","solutions":["Remove or consolidate the duplicate migration so only one exists per (AdapterType, FromVersion).","Bump FromVersion/ToVersion on the new migration so it chains rather than collides.","Audit DI registrations to ensure each migration type is added once."],"exampleFix":"// before\nservices.AddSingleton<IAdapterSettingsMigration>(new MyMigration(1, 2));\nservices.AddSingleton<IAdapterSettingsMigration>(new MyMigrationV2(1, 2)); // duplicate\n// after\nservices.AddSingleton<IAdapterSettingsMigration>(new MyMigrationV2(1, 2));","handlingStrategy":"try-catch","validationCode":"var seen = new HashSet<(string,int)>();\nforeach (var m in migrations)\n    if (!seen.Add((m.AdapterType, m.FromVersion)))\n        throw new InvalidOperationException($\"Duplicate migration for {m.AdapterType} from {m.FromVersion}\");","typeGuard":null,"tryCatchPattern":"try { app = builder.Build(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"more than one migration\"))\n{ /* identify and remove the duplicate registration at startup */ }","preventionTips":["Delete superseded migration classes when adding replacements","Register each migration exactly once in DI","Branch-merge checklist: search for migrations added from the same version"],"tags":["configuration","migration","duplicate"],"backgroundTag":"conflicting-config-options","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}