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

  1. Choose a unique ID for the new converter
  2. Reuse the existing converter instead of registering a duplicate
  3. Match the exact casing of the existing registration if intentional replacement is desired (and remove the old registration first)
  4. 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

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


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)