kubernetes/kops · error

malformed format of PublicIPAddress ID: %s, %d

Error message

malformed format of PublicIPAddress ID: %s, %d

What it means

ParsePublicIPAddressID parses an Azure public IP resource ID of the form /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/publicIPAddresses/<pip> (9 slash-separated parts). If the split yields any other count, the ID is malformed and this error is returned with the observed count. It validates the identifier before constructing a PublicIPAddressID struct.

Source

Thrown at upup/pkg/fi/cloudup/azure/azure_utils.go:166

type PublicIPAddressID struct {
	SubscriptionID      string
	ResourceGroupName   string
	PublicIPAddressName string
}

// String returns the PublicIPAddress ID in the path format.
func (s *PublicIPAddressID) String() string {
	return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/publicIPAddresss/%s",
		s.SubscriptionID,
		s.ResourceGroupName,
		s.PublicIPAddressName)
}

// ParsePublicIPAddressID parses a given PublicIPAddress ID string and returns a PublicIPAddress ID.
func ParsePublicIPAddressID(s string) (*PublicIPAddressID, error) {
	l := strings.Split(s, "/")
	if len(l) != 9 {
		return nil, fmt.Errorf("malformed format of PublicIPAddress ID: %s, %d", s, len(l))
	}
	return &PublicIPAddressID{
		SubscriptionID:      l[2],
		ResourceGroupName:   l[4],
		PublicIPAddressName: l[8],
	}, nil
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Use the full ID: /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Network/publicIPAddresses/<pip-name>.
  2. Get the exact ID via `az network public-ip show -g <rg> -n <pip> --query id`.
  3. Confirm strings.Split(id, "/") has exactly 9 elements before calling.
  4. Check no extra "/" appears inside the PIP name; rename the resource if so.
  5. Correct the spec field referencing the public IP and re-run kops update cluster.

Example fix

// before
pipID = "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses"
// after
pipID = "/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/api-pip"
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate public IP ID shape before parsing
func looksLikeAzurePublicIPID(s string) bool {
    l := strings.Split(s, "/")
    return len(l) == 9 &&
        l[1] == "subscriptions" &&
        l[3] == "resourcegroups" &&
        l[7] == "publicIPAddresses"
}
if !looksLikeAzurePublicIPID(pipID) {
    return fmt.Errorf("expected full public IP resource ID, got %q", pipID)
}

Type guard

func isPublicIPID(s string) bool {
    return strings.HasPrefix(s, "/subscriptions/") &&
        strings.Contains(s, "publicIPAddresses/") &&
        strings.Count(s, "/") == 8
}

Try / catch

parsed, err := azure.ParsePublicIPAddressID(pipID)
if err != nil {
    log.Printf("public IP ID %q malformed (%v); expected /subscriptions/.../publicIPAddresses/<name>", pipID, err)
    return err
}

Prevention

When it happens

Trigger: Calling ParsePublicIPAddressID with a truncated ID missing the public IP name, a bare name like "my-pip", or an ID of a different resource type (subnet = 11 parts, NSG name segment wrong) so the segment count is not 9.

Common situations: Pasting a vNet/subnet ID where a public IP ID is expected; portal copy that dropped the final segment; templated specs where the PIP name variable was empty; public IP renamed or recreated so old stored IDs no longer resolve.

Understand the failure class

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/0190a398fc678162. Report an issue: GitHub.