{"record":{"id":"c4a3d764256670f1","repo":"kubernetes/kops","slug":"malformed-format-of-subnet-id-s-d","errorCode":null,"errorMessage":"malformed format of subnet ID: %s, %d","messagePattern":"malformed format of subnet ID: (.+?), (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/azure/azure_utils.go","lineNumber":65,"sourceCode":"\tResourceGroupName  string\n\tVirtualNetworkName string\n\tSubnetName         string\n}\n\n// String returns the subnet ID in the path format.\nfunc (s *SubnetID) String() string {\n\treturn fmt.Sprintf(\"/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/virtualNetworks/%s/subnets/%s\",\n\t\ts.SubscriptionID,\n\t\ts.ResourceGroupName,\n\t\ts.VirtualNetworkName,\n\t\ts.SubnetName)\n}\n\n// ParseSubnetID parses a given subnet ID string and returns a SubnetID.\nfunc ParseSubnetID(s string) (*SubnetID, error) {\n\tl := strings.Split(s, \"/\")\n\tif len(l) != 11 {\n\t\treturn nil, fmt.Errorf(\"malformed format of subnet ID: %s, %d\", s, len(l))\n\t}\n\treturn &SubnetID{\n\t\tSubscriptionID:     l[2],\n\t\tResourceGroupName:  l[4],\n\t\tVirtualNetworkName: l[8],\n\t\tSubnetName:         l[10],\n\t}, nil\n}\n\n// NetworkSecurityGroupID contains the resource ID/names required to construct a NetworkSecurityGroup ID.\ntype 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 {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/azure/azure_utils.go#L47-L83","documentation":"ParseSubnetID parses an Azure subnet resource ID of the form /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet> (11 slash-separated parts). If the split yields a different number of parts, the ID is malformed and this error is returned with the actual segment count. Returned to callers like the subnet task's Find and unit tests.","triggerScenarios":"Calling ParseSubnetID with a truncated or non-subnet Azure ID string, or a name instead of a full resource ID — e.g. \"/subscriptions/x/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks/vnet\" (9 parts) or \"mySubnet\" (1 part).","commonSituations":"Hand-edited cluster spec with a partial subnet path; copying a vNet ID instead of the subnet ID from the Azure portal; wrong casing/providers section missing causing a different segment count; IDs from a different Azure resource type pasted into subnet fields.","solutions":["Use the full subnet resource ID: /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/virtualNetworks/<vnet>/subnets/<subnet>.","Fetch the canonical ID via `az network vnet subnet show ... --query id` and paste that value.","Verify the count of path segments matches 11 (leading empty segment from the initial slash counts).","Run the TestSubnetIDParse-style check manually: strings.Split(id, \"/\") length must equal 11.","Correct the subnetID field in the cluster/instance-group spec and re-run kops update."],"exampleFix":"// before\nsubnetID = \"/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks/vnet\"\n// after\nsubnetID = \"/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks/vnet/subnets/mysubnet\"","handlingStrategy":"validation","validationCode":"// Go: validate subnet ID shape before parsing\nfunc looksLikeAzureSubnetID(s string) bool {\n    l := strings.Split(s, \"/\")\n    return len(l) == 11 &&\n        l[1] == \"subscriptions\" &&\n        l[3] == \"resourcegroups\" &&\n        l[7] == \"virtualNetworks\" &&\n        l[9] == \"subnets\"\n}\nif !looksLikeAzureSubnetID(subnetID) {\n    return fmt.Errorf(\"expected full subnet resource ID, got %q\", subnetID)\n}","typeGuard":"func isSubnetID(s string) bool {\n    return strings.HasPrefix(s, \"/subscriptions/\") && strings.Count(s, \"/\") == 10\n}","tryCatchPattern":"parsed, err := azure.ParseSubnetID(subnetID)\nif err != nil {\n    log.Printf(\"subnet ID %q malformed (%v); use full /subscriptions/.../subnets/<name> path\", subnetID, err)\n    return err\n}","preventionTips":["Copy resource IDs with az network vnet subnet show --query id, not from hand-typed paths.","Don't paste vNet IDs where subnet IDs are expected.","Avoid truncation when copying from terminal output.","Store canonical Azure IDs in spec/automation variables.","Validate ID segment counts in CI before applying specs."],"tags":["azure","resource-id","parsing","validation"],"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"}