kubernetes/kops · error

private IP for digitalocean droplet was empty

Error message

private IP for digitalocean droplet was empty

What it means

During node bootstrap (evaluateHostnameOverride/evaluateSpec), nodeup queries the DigitalOcean metadata service for the droplet's private IPv4 address and received an empty value. The droplet either has no private networking enabled or the metadata service is not yet populated.

Source

Thrown at upup/pkg/fi/nodeup/command.go:540

		b, err := vfs.Context.ReadFile("metadata://gce/instance/hostname")
		if err != nil {
			return "", fmt.Errorf("error reading hostname from GCE metadata: %v", err)
		}

		// We only want to use the first portion of the fully-qualified name
		// e.g. foo.c.project.internal => foo
		fullyQualified := string(b)
		bareHostname := strings.Split(fullyQualified, ".")[0]
		return bareHostname, nil
	case api.CloudProviderDO:
		vBytes, err := vfs.Context.ReadFile("metadata://digitalocean/interfaces/private/0/ipv4/address")
		if err != nil {
			return "", fmt.Errorf("error reading droplet private IP from DigitalOcean metadata: %v", err)
		}

		hostname := string(vBytes)
		if hostname == "" {
			return "", errors.New("private IP for digitalocean droplet was empty")
		}

		return hostname, nil
	case api.CloudProviderLinode:
		label, err := linodemetadata.GetMetadataValue(context.TODO(), "label")
		if err != nil {
			return "", fmt.Errorf("error reading hostname from Linode metadata: %v", err)
		}

		// Akamai (Linode) cloud-init does not set the OS hostname.
		// Set it here so the OS hostname matches the kubelet hostname override.
		if err := os.WriteFile("/etc/hostname", []byte(label+"\n"), 0o644); err != nil { //nolint:gosec // /etc/hostname is conventionally world-readable system configuration.
			klog.Warningf("Failed to write /etc/hostname: %v", err)
		} else if err := exec.Command("hostname", label).Run(); err != nil {
			klog.Warningf("Failed to set runtime hostname %q: %v", label, err)
		} else {
			klog.Infof("Set OS hostname to %q", label)
		}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure the droplet was created with private networking (a VPC network interface) enabled
  2. Retry after a short delay; metadata may populate shortly after droplet boot
  3. Check the droplet's network interfaces in the DigitalOcean console
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at upup/pkg/fi/nodeup/command.go:540 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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