{"record":{"id":"f69b29043dae99c1","repo":"kubernetes/kops","slug":"malformed-format-of-networksecuritygroup-id-s","errorCode":null,"errorMessage":"malformed format of NetworkSecurityGroup ID: %s, %d","messagePattern":"malformed format of NetworkSecurityGroup ID: (.+?), (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azure/azure_utils.go","lineNumber":94,"sourceCode":"type NetworkSecurityGroupID struct {\n\tSubscriptionID           string\n\tResourceGroupName        string\n\tNetworkSecurityGroupName string\n}\n\n// String returns the NetworkSecurityGroup ID in the path format.\nfunc (s *NetworkSecurityGroupID) String() string {\n\treturn fmt.Sprintf(\"/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/networkSecurityGroups/%s\",\n\t\ts.SubscriptionID,\n\t\ts.ResourceGroupName,\n\t\ts.NetworkSecurityGroupName)\n}\n\n// ParseNetworkSecurityGroupID parses a given NetworkSecurityGroup ID string and returns a NetworkSecurityGroup ID.\nfunc ParseNetworkSecurityGroupID(s string) (*NetworkSecurityGroupID, error) {\n\tl := strings.Split(s, \"/\")\n\tif len(l) != 9 {\n\t\treturn nil, fmt.Errorf(\"malformed format of NetworkSecurityGroup ID: %s, %d\", s, len(l))\n\t}\n\treturn &NetworkSecurityGroupID{\n\t\tSubscriptionID:           l[2],\n\t\tResourceGroupName:        l[4],\n\t\tNetworkSecurityGroupName: l[8],\n\t}, nil\n}\n\n// ApplicationSecurityGroupID contains the resource ID/names required to construct a ApplicationSecurityGroup ID.\ntype ApplicationSecurityGroupID struct {\n\tSubscriptionID               string\n\tResourceGroupName            string\n\tApplicationSecurityGroupName string\n}\n\n// String returns the ApplicationSecurityGroup ID in the path format.\nfunc (s *ApplicationSecurityGroupID) String() string {\n\treturn fmt.Sprintf(\"/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/applicationSecurityGroups/%s\",","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azure/azure_utils.go#L76-L112","documentation":"ParseNetworkSecurityGroupID parses an Azure NSG resource ID of the form /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/networkSecurityGroups/<nsg> (9 slash-separated parts). If the split count differs, the ID is malformed and this error is returned with the observed count. It guards against malformed identifiers before constructing the NetworkSecurityGroupID struct.","triggerScenarios":"Calling ParseNetworkSecurityGroupID with a truncated ID, a plain NSG name, or an ID of another resource type — e.g. \"/subscriptions/x/resourceGroups/rg/providers/Microsoft.Network/networkSecurityGroups\" (8 parts, missing the name) or a subnet ID (11 parts).","commonSituations":"Pasting a truncated ID from the portal (dropping the NSG name); mixing up NSG and subnet/load balancer IDs in cluster spec fields; templating errors that cut the path; IDs copied from CLI output that was truncated by terminal width.","solutions":["Provide the complete ID: /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/networkSecurityGroups/<nsg-name>.","Get the exact ID with `az network nsg show -g <rg> -n <nsg> --query id`.","Check the slash-segment count is 9 before passing it in.","Ensure the NSG name itself contains no \"/\" (would change the count); rename if necessary.","Fix the referencing field in the cluster spec and re-run kops update cluster."],"exampleFix":"// before\nnsgID = \"/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/networkSecurityGroups\"\n// after\nnsgID = \"/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/networkSecurityGroups/my-nsg\"","handlingStrategy":"validation","validationCode":"// Go: validate NSG ID shape before parsing\nfunc looksLikeAzureNSGID(s string) bool {\n    l := strings.Split(s, \"/\")\n    return len(l) == 9 &&\n        l[1] == \"subscriptions\" &&\n        l[3] == \"resourcegroups\" &&\n        l[7] == \"networkSecurityGroups\"\n}\nif !looksLikeAzureNSGID(nsgID) {\n    return fmt.Errorf(\"expected full NSG resource ID, got %q\", nsgID)\n}","typeGuard":"func isNSGID(s string) bool {\n    return strings.HasPrefix(s, \"/subscriptions/\") &&\n        strings.Contains(s, \"networkSecurityGroups/\") &&\n        strings.Count(s, \"/\") == 8\n}","tryCatchPattern":"parsed, err := azure.ParseNetworkSecurityGroupID(nsgID)\nif err != nil {\n    log.Printf(\"NSG ID %q malformed (%v); expected /subscriptions/.../networkSecurityGroups/<name>\", nsgID, err)\n    return err\n}","preventionTips":["Fetch NSG IDs with az network nsg show --query id.","Don't substitute subnet or load balancer IDs in NSG fields.","Beware terminal-wrapped CLI output truncating the ID's final segment.","Avoid \"/\" in NSG resource names.","Validate Azure IDs in CI before cluster updates."],"tags":["azure","resource-id","parsing","nsg"],"backgroundTag":"malformed-azure-resource-id","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}