elsa-workflows/elsa-core · error · InvalidOperationException
Output converter ID ' ' is already registered or differs…
Error message
Output converter ID '{id}' is already registered or differs from '{existingRegistration.Descriptor.Id}' only by case. What it means
ValidateUniqueId checks existing OutputConverterRegistration entries case-insensitively and throws InvalidOperationException when the ID is already registered or differs only by case. This prevents ambiguous converter resolution. Registration happens via AddOutputConverter on the IServiceCollection.
Solutions
- Choose a unique ID for the new converter
- Reuse the existing converter instead of registering a duplicate
- Match the exact casing of the existing registration if intentional replacement is desired (and remove the old registration first)
- Check registered OutputConverterRegistration entries in the DI container before adding
Example fix
// before
services.AddOutputConverter(new OutputConverterDescriptor { Id = "XML" });
// after
services.AddOutputConverter(new OutputConverterDescriptor { Id = "application/xml" }); Defensive patterns
Strategy: validation
Validate before calling
var taken = services.Where(x => x.ServiceType == typeof(OutputConverterRegistration)).OfType<IServiceProviderIsService>().Any(); // or inspect registrations for a matching Descriptor.Id (OrdinalIgnoreCase) before adding
Type guard
static bool IsDuplicateId(IServiceCollection s, string id) => s.Where(x => x.ServiceType == typeof(OutputConverterRegistration)).Select(x => x.ImplementationInstance).OfType<OutputConverterRegistration>().Any(r => string.Equals(r.Descriptor.Id, id, StringComparison.OrdinalIgnoreCase));
Try / catch
try { services.AddOutputConverter(descriptor); } catch (InvalidOperationException ex) when (ex.Message.Contains("Output converter ID")) { logger.LogWarning(ex, "Duplicate output converter id skipped"); } Prevention
- Use stable, descriptive IDs (media types) and keep a registry of them
- Avoid case-variant duplicates by normalizing IDs to lowercase before registering
When it happens
Trigger: Registering two output converters whose IDs collide (e.g. "xml" vs "XML"); a library already registers a converter with the same ID; re-running registration code twice in the same service collection.
Common situations: Two modules each registering a converter for the same media type with the same ID; duplicate feature auto-registration; case inconsistency between registrations.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- A workflow resumer is required to complete a User Task.
- Build() must be called before accessing services
- Duplicate ingress source registration for name
- External Authentication handle-hashing settings are…
- Multiple handlers were found to handle the
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/c997088652ee1a84.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Workflows.Core/Extensions/OutputConverterServiceCollectionExtensions.cs:51
typeof(TConverter),
serviceLifetime));
services.TryAddSingleton<IOutputConverterRegistry, OutputConverterRegistry>();
return services;
}
private static void ValidateUniqueId(IServiceCollection services, string id)
{
if (string.IsNullOrWhiteSpace(id))
throw new ArgumentException("Output converter IDs cannot be empty.", nameof(id));
var existingRegistration = services
.Where(x => x.ServiceType == typeof(OutputConverterRegistration))
.Select(x => x.ImplementationInstance)
.OfType<OutputConverterRegistration>()
.FirstOrDefault(x => string.Equals(x.Descriptor.Id, id, StringComparison.OrdinalIgnoreCase));
if (existingRegistration != null)
throw new InvalidOperationException($"Output converter ID '{id}' is already registered or differs from '{existingRegistration.Descriptor.Id}' only by case.");
}
}
View on GitHub (pinned to fe9217bdfa)