microsoft/aspire · error · ArgumentException
A security rule named
Error message
A security rule named '{rule.Name}' already exists in Network Security Group '{builder.Resource.Name}'. What it means
WithSecurityRule adds a security rule to an Azure Network Security Group resource. Aspire rejects duplicate rule names (case-insensitive comparison) with ArgumentException because NSG security rules must be uniquely named within the NSG.
Solutions
- Rename one of the rules so names are unique within the NSG.
- Make generated names unique by appending an index or port, e.g. $"allow-{port}".
- Check for duplicate WithSecurityRule calls in loops or helper methods.
- Pre-check with builder.Resource.SecurityRules before adding if names are dynamic.
Example fix
// before
nsg.WithSecurityRule(new SecurityRule { Name = "allow-http", ... });
nsg.WithSecurityRule(new SecurityRule { Name = "Allow-HTTP", ... });
// after
nsg.WithSecurityRule(new SecurityRule { Name = "allow-http", ... });
nsg.WithSecurityRule(new SecurityRule { Name = "allow-https", ... }); Defensive patterns
Strategy: validation
Validate before calling
if (builder.Resource.SecurityRules.Any(r => string.Equals(r.Name, rule.Name, StringComparison.OrdinalIgnoreCase)))
throw new ArgumentException($"Rule '{rule.Name}' already exists in NSG '{builder.Resource.Name}'."); Try / catch
try { nsgBuilder.WithSecurityRule(rule); }
catch (ArgumentException ex) when (ex.Message.Contains("already exists")) { /* skip or rename the duplicate rule */ } Prevention
- Generate rule names from unique inputs (port, purpose, target).
- Avoid fixed constant names in loops that add multiple rules.
- Remember names are compared case-insensitively — 'Allow-HTTP' and 'allow-http' collide.
- List existing rules before adding dynamically named ones.
When it happens
Trigger: Calling WithSecurityRule twice on the same NSG builder with rules whose Name properties are equal ignoring case, e.g. 'allow-http' and 'Allow-HTTP'.
Common situations: Loop-driven rule setup where names are generated with the same template, copy-pasted rule definitions, or conditional calls that both add a rule with a shared constant name.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- An access rule named
- An association named
- A circular lifetime reference was detected for resource
- A global MCP approval policy cannot be combined with custom…
- adminPassword
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/1a96f87c6ec01e27.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityGroupExtensions.cs:101
/// Direction = SecurityRuleDirection.Inbound,
/// Access = SecurityRuleAccess.Deny,
/// Protocol = SecurityRuleProtocol.Asterisk,
/// DestinationPortRange = "*"
/// });
/// </code>
/// </example>
[AspireExport]
public static IResourceBuilder<AzureNetworkSecurityGroupResource> WithSecurityRule(
this IResourceBuilder<AzureNetworkSecurityGroupResource> builder,
AzureSecurityRule rule)
{
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(rule);
ArgumentException.ThrowIfNullOrEmpty(rule.Name);
if (builder.Resource.SecurityRules.Any(existing => string.Equals(existing.Name, rule.Name, StringComparison.OrdinalIgnoreCase)))
{
throw new ArgumentException(
$"A security rule named '{rule.Name}' already exists in Network Security Group '{builder.Resource.Name}'.",
nameof(rule));
}
builder.Resource.SecurityRules.Add(rule);
return builder;
}
private static void ConfigureNetworkSecurityGroup(AzureResourceInfrastructure infra)
{
var azureResource = (AzureNetworkSecurityGroupResource)infra.AspireResource;
var nsg = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infra,
(identifier, name) =>
{
var resource = NetworkSecurityGroup.FromExisting(identifier);
resource.Name = name;
return resource;View on GitHub (pinned to 25830f84bd)