OrchardCMS/OrchardCore · error · ArgumentException
A feature is missing a mandatory 'Id' property in the Module
Error message
A feature is missing a mandatory 'Id' property in the Module '{extensionInfo.Id}' What it means
FeaturesProvider builds the feature list for each module extension during module discovery. Every feature exposed by a module must carry a non-empty Id, since feature ids are the primary key for activation, dependency resolution, and DI mapping. If an extension declares a feature whose Id is null, empty, or whitespace, discovery is aborted with this ArgumentException.
Solutions
- Set the Id property on every [Feature] attribute or feature descriptor in the offending module (the module name is in the exception message).
- Ensure feature Ids are non-empty strings, conventionally 'ModuleName.FeatureName' for secondary features.
- Rebuild the module so updated attribute metadata is loaded, then restart the application.
Example fix
// before
[Feature(Name = "Sample Feature")]
public class Startup : StartupBase { }
// after
[Feature(Id = "My.SampleModule", Name = "Sample Feature")]
public class Startup : StartupBase { } Defensive patterns
Strategy: validation
Validate before calling
var features = extensionInfo.Features ?? [];
if (features.Any(f => string.IsNullOrWhiteSpace(f.Id)))
throw new InvalidOperationException($"Module '{extensionInfo.Id}' has a feature without an Id."); Type guard
bool HasValidId(IFeature feature) => !string.IsNullOrWhiteSpace(feature.Id);
Try / catch
try { provider.GetFeatures(extensionInfo); }
catch (ArgumentException ex) { _logger.LogError(ex, "Module {Module} has a feature missing its Id", extensionInfo.Id); } Prevention
- Always set Id on [Feature] attributes; use ModuleName.FeatureName convention for secondary features.
- Add a unit test asserting every module's features have non-empty Ids.
- Never rename/remove the Id property of feature attributes without grepping all modules.
When it happens
Trigger: Calling GetFeatures(extensionInfo) where the extension's feature list (typically constructed from [Feature] attributes or an IFeatureProvider) contains an entry whose Id property is null, empty, or whitespace.
Common situations: A custom module declares [Feature(Name = "My Feature")] without setting Id; a hand-written IFeatureAttributeConfiguration misconfigures attribute property binding; a refactor renames or removes the Id property from a feature attribute.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Could not resolve extension for type
- Could not resolve main feature for type
- Could not resolve features for type
- The configured table name separator
- The configured identity column size
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/373e396d63ca0caa.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore/Extensions/Features/FeaturesProvider.cs:29
/// <param name="featureBuilderEvents"></param>
public FeaturesProvider(IEnumerable<IFeatureBuilderEvents> featureBuilderEvents)
: base(featureBuilderEvents)
{
}
public override IEnumerable<IFeatureInfo> GetFeatures(IExtensionInfo extensionInfo, IManifestInfo manifestInfo)
{
var featuresInfos = new List<IFeatureInfo>();
// Features and Dependencies live within this section
var features = manifestInfo.ModuleInfo.Features;
if (features.Count > 0)
{
foreach (var feature in features)
{
if (string.IsNullOrWhiteSpace(feature.Id))
{
throw new ArgumentException(
$"A {nameof(feature)} is missing a mandatory '{nameof(feature.Id)}' property in the Module '{extensionInfo.Id}'");
}
// Attribute properties are transparently resolved by the instances themselves for convenience
var featureId = feature.Id;
var featureName = feature.Name;
var featureDependencyIds = feature.Dependencies;
var featureBeforeDependencyIds = feature.Before;
var featureAfterDependencyIds = feature.After;
// Categorize, Prioritize, Describe, using the ModuleInfo (ModuleAttribute) as the back stop
var featureCategory = feature.Categorize(manifestInfo.ModuleInfo);
var featurePriority = feature.Prioritize(manifestInfo.ModuleInfo);
var featureDescription = feature.Describe(manifestInfo.ModuleInfo);
var featureDefaultTenantOnly = feature.DefaultTenantOnly;
var featureIsAlwaysEnabled = feature.IsAlwaysEnabled;
var featureEnabledByDependencyOnly = feature.EnabledByDependencyOnly;View on GitHub (pinned to 4306c0717f)