OrchardCMS/OrchardCore · error · InvalidOperationException
Could not resolve features for type
Error message
Could not resolve features for type {dependency.Name}. What it means
GetFeaturesForDependency returns all features associated with a DI service type. Because the provider only knows types that were registered through TryAdd during feature type discovery, an unregistered type yields no entry and this InvalidOperationException is thrown rather than returning an empty list.
Solutions
- Register the service from a module's Startup/StartupBase class so feature discovery maps it.
- Only query types resolved from the shell's module-scoped container.
- In tests, populate the provider with TryAdd for the types under inspection before querying.
Example fix
// before var features = provider.GetFeaturesForDependency(typeof(ManuallyRegisteredService)); // throws // after provider.TryAdd(typeof(ManuallyRegisteredService), moduleFeature); var features = provider.GetFeaturesForDependency(typeof(ManuallyRegisteredService));
Defensive patterns
Strategy: type-guard
Validate before calling
bool registered =
((IEnumerable<KeyValuePair<Type, IFeatureInfo[]>>)provider.GetRegisteredTypes())
.Any(kv => kv.Key == typeof(T)); // expose or mirror the map if the API allows Type guard
bool IsFeatureMapped(Type dependency)
{
try { provider.GetFeaturesForDependency(dependency); return true; }
catch (InvalidOperationException) { return false; }
} Try / catch
try { var features = provider.GetFeaturesForDependency(type); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Could not resolve features")) { features = []; } Prevention
- Call TryAdd for every type you plan to look up later, including in test harnesses.
- Restrict feature-map queries to types resolved from module DI containers.
- Avoid registering essential services directly on the root service collection.
When it happens
Trigger: Calling GetFeaturesForDependency(type) for a type not registered by any module startup — the ConcurrentDictionary lookup misses and the throw executes.
Common situations: Inspecting services added directly to the service collection (host or theme-level) rather than via module Startup; calling during unit tests with a partially populated TypeFeatureProvider.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Could not resolve extension for type
- Could not resolve main feature for type
- A feature is missing a mandatory 'Id' property in the Module
- The type can only be assigned to a single feature. Make…
- The 'Default' feature is not registered.
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/6a58a2a9e44d7c58.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore/Extensions/Features/TypeFeatureProvider.cs:39
{
if (_features.TryGetValue(dependency, out var features))
{
// Gets the first feature that has the same ID as the extension, if any.
// Otherwise returns the first feature.
return features.FirstOrDefault(feature => feature.Extension.Id == feature.Id) ?? features.First();
}
throw new InvalidOperationException($"Could not resolve main feature for type {dependency.Name}.");
}
public IEnumerable<IFeatureInfo> GetFeaturesForDependency(Type dependency)
{
if (_features.TryGetValue(dependency, out var features))
{
return features;
}
throw new InvalidOperationException($"Could not resolve features for type {dependency.Name}.");
}
public IEnumerable<Type> GetTypesForFeature(IFeatureInfo feature)
{
return _features.Where(kv => kv.Value.Contains(feature)).Select(kv => kv.Key);
}
public void TryAdd(Type type, IFeatureInfo feature)
{
var features = _features.AddOrUpdate(type, (key, value) => [value], (key, features, value) => features.Contains(value) ? features : features.Append(value).ToArray(), feature);
if (features.Count() > 1 && (FeatureTypeDiscoveryAttribute.GetFeatureTypeDiscoveryForType(type)?.SingleFeatureOnly ?? false))
{
throw new InvalidOperationException($"The type {type} can only be assigned to a single feature. Make sure the type is not added to DI by multiple startup classes.");
}
}
}
View on GitHub (pinned to 4306c0717f)