{"record":{"id":"1a96f87c6ec01e27","repo":"microsoft/aspire","slug":"a-security-rule-named-rule-name-already-exists-in-network","errorCode":null,"errorMessage":"A security rule named '{rule.Name}' already exists in Network Security Group '{builder.Resource.Name}'.","messagePattern":"A security rule named '(.+?)' already exists in Network Security Group '(.+?)'\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityGroupExtensions.cs","lineNumber":101,"sourceCode":"    ///         Direction = SecurityRuleDirection.Inbound,\n    ///         Access = SecurityRuleAccess.Deny,\n    ///         Protocol = SecurityRuleProtocol.Asterisk,\n    ///         DestinationPortRange = \"*\"\n    ///     });\n    /// </code>\n    /// </example>\n    [AspireExport]\n    public static IResourceBuilder<AzureNetworkSecurityGroupResource> WithSecurityRule(\n        this IResourceBuilder<AzureNetworkSecurityGroupResource> builder,\n        AzureSecurityRule rule)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentNullException.ThrowIfNull(rule);\n        ArgumentException.ThrowIfNullOrEmpty(rule.Name);\n\n        if (builder.Resource.SecurityRules.Any(existing => string.Equals(existing.Name, rule.Name, StringComparison.OrdinalIgnoreCase)))\n        {\n            throw new ArgumentException(\n                $\"A security rule named '{rule.Name}' already exists in Network Security Group '{builder.Resource.Name}'.\",\n                nameof(rule));\n        }\n\n        builder.Resource.SecurityRules.Add(rule);\n        return builder;\n    }\n\n    private static void ConfigureNetworkSecurityGroup(AzureResourceInfrastructure infra)\n    {\n        var azureResource = (AzureNetworkSecurityGroupResource)infra.AspireResource;\n\n        var nsg = AzureProvisioningResource.CreateExistingOrNewProvisionableResource(infra,\n            (identifier, name) =>\n            {\n                var resource = NetworkSecurityGroup.FromExisting(identifier);\n                resource.Name = name;\n                return resource;","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityGroupExtensions.cs#L83-L119","documentation":"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.","triggerScenarios":"Calling WithSecurityRule twice on the same NSG builder with rules whose Name properties are equal ignoring case, e.g. 'allow-http' and 'Allow-HTTP'.","commonSituations":"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.","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."],"exampleFix":"// before\nnsg.WithSecurityRule(new SecurityRule { Name = \"allow-http\", ... });\nnsg.WithSecurityRule(new SecurityRule { Name = \"Allow-HTTP\", ... });\n// after\nnsg.WithSecurityRule(new SecurityRule { Name = \"allow-http\", ... });\nnsg.WithSecurityRule(new SecurityRule { Name = \"allow-https\", ... });","handlingStrategy":"validation","validationCode":"if (builder.Resource.SecurityRules.Any(r => string.Equals(r.Name, rule.Name, StringComparison.OrdinalIgnoreCase)))\n    throw new ArgumentException($\"Rule '{rule.Name}' already exists in NSG '{builder.Resource.Name}'.\");","typeGuard":null,"tryCatchPattern":"try { nsgBuilder.WithSecurityRule(rule); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"already exists\")) { /* skip or rename the duplicate rule */ }","preventionTips":["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."],"tags":["aspire","azure-network","nsg","duplicate-name"],"backgroundTag":"file-already-exists","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}