{"record":{"id":"7d6e4fa7250d49e1","repo":"microsoft/aspire","slug":"the-subnet-builder-resource-name-already-has-an-nsg-created","errorCode":null,"errorMessage":"The subnet '{builder.Resource.Name}' already has an NSG created via shorthand methods. Calling WithNetworkSecurityGroup would replace the existing NSG and discard those rules. Use either shorthand methods (AllowInbound, DenyInbound, etc.) or an explicit NSG, not both.","messagePattern":"The subnet '(.+?)' already has an NSG created via shorthand methods\\. Calling WithNetworkSecurityGroup would replace the existing NSG and discard those rules\\. Use either shorthand methods \\(AllowInbound, DenyInbound, etc\\.\\) or an explicit NSG, not both\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.Network/AzureVirtualNetworkExtensions.cs","lineNumber":471,"sourceCode":"    ///     .WithNetworkSecurityGroup(nsg);\n    /// </code>\n    /// </example>\n    /// <exception cref=\"InvalidOperationException\">\n    /// Thrown when the subnet already has security rules added via shorthand methods\n    /// (<see cref=\"AllowInbound\"/>, <see cref=\"DenyInbound\"/>, <see cref=\"AllowOutbound\"/>, <see cref=\"DenyOutbound\"/>).\n    /// Use either shorthand methods or an explicit NSG, not both.\n    /// </exception>\n    [AspireExport]\n    public static IResourceBuilder<AzureSubnetResource> WithNetworkSecurityGroup(\n        this IResourceBuilder<AzureSubnetResource> builder,\n        IResourceBuilder<AzureNetworkSecurityGroupResource> nsg)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentNullException.ThrowIfNull(nsg);\n\n        if (builder.Resource.NetworkSecurityGroup is { IsImplicitlyCreated: true })\n        {\n            throw new InvalidOperationException(\n                $\"The subnet '{builder.Resource.Name}' already has an NSG created via shorthand methods. \" +\n                $\"Calling WithNetworkSecurityGroup would replace the existing NSG and discard those rules. \" +\n                $\"Use either shorthand methods (AllowInbound, DenyInbound, etc.) or an explicit NSG, not both.\");\n        }\n\n        builder.Resource.NetworkSecurityGroup = nsg.Resource;\n        return builder;\n    }\n\n    /// <summary>\n    /// Adds an inbound allow rule to the subnet's Network Security Group.\n    /// </summary>\n    /// <param name=\"builder\">The subnet resource builder.</param>\n    /// <param name=\"port\">The destination port range (e.g., \"443\", \"80-443\"). Defaults to \"*\" (any).</param>\n    /// <param name=\"from\">The source address prefix (e.g., \"AzureLoadBalancer\", \"Internet\", \"10.0.0.0/8\"). Defaults to \"*\" (any).</param>\n    /// <param name=\"to\">The destination address prefix. Defaults to \"*\" (any).</param>\n    /// <param name=\"protocol\">The network protocol. Defaults to <see cref=\"SecurityRuleProtocol.Asterisk\"/> (any).</param>\n    /// <param name=\"priority\">The rule priority (100-4096). If not specified, auto-increments from 100 by 100.</param>","sourceCodeStart":453,"sourceCodeEnd":489,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.Network/AzureVirtualNetworkExtensions.cs#L453-L489","documentation":"AzureSubnetResource can hold exactly one NSG. If shorthand rule methods (AllowInbound, DenyInbound, etc.) were used, the resource carries an implicitly created NSG; calling WithNetworkSecurityGroup with an explicit NSG builder would overwrite it and silently discard all rules added via shorthand. The method detects IsImplicitlyCreated and throws InvalidOperationException to force choosing one approach.","triggerScenarios":"Calling subnet.WithNetworkSecurityGroup(nsg) after any shorthand call such as subnet.AllowInbound(...)/DenyInbound(...) on the same subnet resource.","commonSituations":"Mixing a documented explicit-NSG snippet with existing shorthand rule code; moving from quick shorthand rules to a full NSG definition during refactoring; two team members contributing rules in different styles to the same subnet.","solutions":["Remove the WithNetworkSecurityGroup call and keep using shorthand methods (AllowInbound/DenyInbound/AllowOutbound/DenyOutbound).","Alternatively remove all shorthand rule calls and define the NSG fully via WithNetworkSecurityGroup.","If you truly want to replace, first reset the subnet's NetworkSecurityGroup (clear the implicitly created NSG) before attaching the explicit one.","Audit the subnet resource's NetworkSecurityGroup property to confirm which style is in use before adding rules."],"exampleFix":"// before\nsubnet.AllowInbound(\"allow-http\", 80);\nsubnet.WithNetworkSecurityGroup(nsg); // throws\n\n// after\nsubnet.WithNetworkSecurityGroup(nsg); // explicit NSG defines all rules","handlingStrategy":"validation","validationCode":"if (subnet.Resource.NetworkSecurityGroup is { IsImplicitlyCreated: true })\n{\n    // shorthand rules exist; do not call WithNetworkSecurityGroup\n}","typeGuard":null,"tryCatchPattern":"try { subnet.WithNetworkSecurityGroup(nsg); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"shorthand methods\")) { /* pick one style: keep shorthand rules or drop them and use the explicit NSG */ }","preventionTips":["Pick one NSG style per subnet: either shorthand rule methods or an explicit NSG builder, never both.","Document the chosen style in the AppHost so contributors follow it.","Before adding rules, inspect subnet.Resource.NetworkSecurityGroup to see what already exists."],"tags":["azure","networking","nsg","mutually-exclusive"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}