kubernetes/kops · error

failed to initialize digitalocean cloud: %s

Error message

failed to initialize digitalocean cloud: %s

What it means

After resolving the region, New() instantiates the DigitalOcean API client via NewCloud(region) (godo client with an OAuth token). Failure here — typically a missing/invalid DO API token — is wrapped as "failed to initialize digitalocean cloud". The nodeidentifier cannot proceed without a working DO client.

Source

Thrown at pkg/nodeidentity/do/identify.go:72

type TokenSource struct {
	AccessToken string
}

// Token returns an oauth2.Token for the configured access token.
func (t *TokenSource) Token() (*oauth2.Token, error) {
	return &oauth2.Token{AccessToken: t.AccessToken}, nil
}

// New creates and returns a nodeidentity.Identifier for nodes running on DigitalOcean.
func New(cacheNodeidentityInfo bool) (nodeidentity.Identifier, error) {
	region, err := getMetadataRegion()
	if err != nil {
		return nil, fmt.Errorf("failed to get droplet region: %s", err)
	}

	doClient, err := NewCloud(region)
	if err != nil {
		return nil, fmt.Errorf("failed to initialize digitalocean cloud: %s", err)
	}

	return &nodeIdentifier{
		doClient:     doClient,
		cache:        expirationcache.NewTTLStore(stringKeyFunc, cacheTTL),
		cacheEnabled: cacheNodeidentityInfo,
	}, nil
}

func getMetadataRegion() (string, error) {
	return getMetadata(dropletRegionMetadataURL)
}

// NewCloud returns a godo client, expecting the env var DIGITALOCEAN_ACCESS_TOKEN to be set.
func NewCloud(region string) (*godo.Client, error) {
	accessToken := os.Getenv("DIGITALOCEAN_ACCESS_TOKEN")
	if accessToken == "" {
		return nil, errors.New("DIGITALOCEAN_ACCESS_TOKEN is required")

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Set the DO API token env var expected by NewCloud (check the code for the exact name, e.g. DIGITALOCEAN_ACCESS_TOKEN) and restart the component.
  2. Verify the token is valid: curl -H 'Authorization: Bearer <token>' https://api.digitalocean.com/v2/account.
  3. Generate a new read/write token in the DO control panel if the old one was revoked.
  4. Check the secret/config mount path so the token is actually present at process start.

Example fix

// before: systemd unit without token
[Service]
ExecStart=/usr/local/bin/kops-node-identity

// after
[Service]
EnvironmentFile=/etc/kops/do-token
ExecStart=/usr/local/bin/kops-node-identity
# /etc/kops/do-token: DIGITALOCEAN_ACCESS_TOKEN=dop_v1_xxxx
Defensive patterns

Strategy: validation

Validate before calling

token := os.Getenv("DIGITALOCEAN_ACCESS_TOKEN")
if token == "" {
    return fmt.Errorf("DIGITALOCEAN_ACCESS_TOKEN must be set before initializing the DO cloud")
}
req, _ := http.NewRequest("GET", "https://api.digitalocean.com/v2/account", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil || resp.StatusCode != http.StatusOK {
    return fmt.Errorf("DO token missing or invalid")
}

Try / catch

id, err := nodeidentity.New(true)
if err != nil && strings.Contains(err.Error(), "failed to initialize digitalocean cloud") {
    return fmt.Errorf("check DO API token env/secret: %w", err)
}

Prevention

When it happens

Trigger: NewCloud fails because the digitalocean token environment variable (e.g. DIGITALOCEAN_ACCESS_TOKEN / OS credential file) is unset or malformed, the oauth2 client cannot be constructed, or an invalid token format is supplied.

Common situations: Deploying kops on DO without setting the DO API token in the environment or cloud config; token rotated/revoked but old config still deployed; typos in env var names in systemd unit or container spec; empty token after failed secret mount.

Related errors


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