stride3d/stride · error · InvalidOperationException

Multiple services match the given type.

Error message

Multiple services match the given type.

What it means

Thrown by ViewModelServiceProvider.TryGet when more than one registered service is an instance of the requested serviceType. TryGet is meant to resolve a single unambiguous service; the provider's services list is not keyed by type, so a request matching multiple registrations is ambiguous and cannot be answered, hence the InvalidOperationException. It fires when the same service type (or compatible base/interface) was registered twice.

Solutions

  1. Register each service under exactly one unambiguous type and query for the most specific type
  2. Remove the redundant registration that makes the match ambiguous
  3. Iterate the raw service list yourself if you truly need multiple matches

Example fix

// before
provider.RegisterService(myServiceImpl);      // matches IMyService and MyBase
provider.RegisterService((MyBase)myServiceImpl); // ambiguous
var svc = provider.TryGet(typeof(IMyService)); // throws
// after
provider.RegisterService(myServiceImpl); // register once
var svc = provider.TryGet(typeof(IMyService));
Defensive patterns

Strategy: validation

Validate before calling

var candidates = new List<object>();
foreach (var s in services) if (serviceType.IsInstanceOfType(s)) candidates.Add(s);
if (candidates.Count > 1) throw new InvalidOperationException("Ambiguous registrations: " + serviceType.Name);

Try / catch

try { svc = provider.TryGet(typeof(IMyService)); }
catch (InvalidOperationException ex) { log.Error(ex, "Ambiguous service registrations"); svc = null; }

Prevention

When it happens

Trigger: Registering two services where both are instances of serviceType (e.g. one type implementing two registered interfaces, or a subclass registered alongside its base), then calling TryGet/Get for the shared type.

Common situations: Registering an interface and a base class that both match one instance; duplicate services registered under related types; parent provider + local provider ambiguities resolved in the loop before the parent fallback.

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 stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/b9788f3d7790a7b5. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation/ViewModels/ViewModelServiceProvider.cs:84

        ArgumentNullException.ThrowIfNull(service);

        if (services.Remove(service))
        {
            ServiceUnregistered?.Invoke(this, new ServiceRegistrationEventArgs(service));
        }
    }

    /// <inheritdoc/>
    public object? TryGet(Type serviceType)
    {
        ArgumentNullException.ThrowIfNull(serviceType);

        object? serviceFound = null;

        foreach (var service in services.Where(serviceType.IsInstanceOfType))
        {
            if (serviceFound != null)
                throw new InvalidOperationException("Multiple services match the given type.");

            serviceFound = service;
        }

        return serviceFound ?? parentProvider?.TryGet(serviceType);
    }

    /// <inheritdoc/>
    public T? TryGet<T>() where T : class
    {
        return TryGet(typeof(T)) as T;
    }

    /// <inheritdoc/>
    public object Get(Type serviceType)
    {
        var result = TryGet(serviceType);
        return result ?? throw new InvalidOperationException("No service matches the given type.");

View on GitHub (pinned to 96fad776d2)