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
- 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.
- Verify the token is valid: curl -H 'Authorization: Bearer <token>' https://api.digitalocean.com/v2/account.
- Generate a new read/write token in the DO control panel if the old one was revoked.
- 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
- Set the DO API token via EnvironmentFile or mounted secret at process start
- Validate the token with GET /v2/account in a readiness check
- Rotate tokens on a schedule and update deployments atomically
- Avoid hardcoding tokens; reference secrets only
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
- unhandled LoadBalancer type %q
- DIGITALOCEAN_ACCESS_TOKEN is required
- DIGITALOCEAN_ACCESS_TOKEN is required
- node identity is required
- getting rest config: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/a2749ac377d8392a.
Report an issue: GitHub.