{"record":{"id":"6a58a2a9e44d7c58","repo":"OrchardCMS/OrchardCore","slug":"could-not-resolve-features-for-type-dependency-name","errorCode":null,"errorMessage":"Could not resolve features for type {dependency.Name}.","messagePattern":"Could not resolve features for type (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore/Extensions/Features/TypeFeatureProvider.cs","lineNumber":39,"sourceCode":"    {\n        if (_features.TryGetValue(dependency, out var features))\n        {\n            // Gets the first feature that has the same ID as the extension, if any. \n            // Otherwise returns the first feature.\n            return features.FirstOrDefault(feature => feature.Extension.Id == feature.Id) ?? features.First();\n        }\n\n        throw new InvalidOperationException($\"Could not resolve main feature for type {dependency.Name}.\");\n    }\n\n    public IEnumerable<IFeatureInfo> GetFeaturesForDependency(Type dependency)\n    {\n        if (_features.TryGetValue(dependency, out var features))\n        {\n            return features;\n        }\n\n        throw new InvalidOperationException($\"Could not resolve features for type {dependency.Name}.\");\n    }\n\n    public IEnumerable<Type> GetTypesForFeature(IFeatureInfo feature)\n    {\n        return _features.Where(kv => kv.Value.Contains(feature)).Select(kv => kv.Key);\n    }\n\n    public void TryAdd(Type type, IFeatureInfo feature)\n    {\n        var features = _features.AddOrUpdate(type, (key, value) => [value], (key, features, value) => features.Contains(value) ? features : features.Append(value).ToArray(), feature);\n\n        if (features.Count() > 1 && (FeatureTypeDiscoveryAttribute.GetFeatureTypeDiscoveryForType(type)?.SingleFeatureOnly ?? false))\n        {\n            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.\");\n        }\n    }\n}\n","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore/Extensions/Features/TypeFeatureProvider.cs#L21-L57","documentation":"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.","triggerScenarios":"Calling GetFeaturesForDependency(type) for a type not registered by any module startup — the ConcurrentDictionary lookup misses and the throw executes.","commonSituations":"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.","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."],"exampleFix":"// before\nvar features = provider.GetFeaturesForDependency(typeof(ManuallyRegisteredService)); // throws\n\n// after\nprovider.TryAdd(typeof(ManuallyRegisteredService), moduleFeature);\nvar features = provider.GetFeaturesForDependency(typeof(ManuallyRegisteredService));","handlingStrategy":"type-guard","validationCode":"bool registered =\n    ((IEnumerable<KeyValuePair<Type, IFeatureInfo[]>>)provider.GetRegisteredTypes())\n        .Any(kv => kv.Key == typeof(T)); // expose or mirror the map if the API allows","typeGuard":"bool IsFeatureMapped(Type dependency)\n{\n    try { provider.GetFeaturesForDependency(dependency); return true; }\n    catch (InvalidOperationException) { return false; }\n}","tryCatchPattern":"try { var features = provider.GetFeaturesForDependency(type); }\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Could not resolve features\")) { features = []; }","preventionTips":["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."],"tags":["dependency-injection","modules","features"],"backgroundTag":"resource-not-found","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}