{"record":{"id":"a2749ac377d8392a","repo":"kubernetes/kops","slug":"failed-to-initialize-digitalocean-cloud-s","errorCode":null,"errorMessage":"failed to initialize digitalocean cloud: %s","messagePattern":"failed to initialize digitalocean cloud: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodeidentity/do/identify.go","lineNumber":72,"sourceCode":"type TokenSource struct {\n\tAccessToken string\n}\n\n// Token returns an oauth2.Token for the configured access token.\nfunc (t *TokenSource) Token() (*oauth2.Token, error) {\n\treturn &oauth2.Token{AccessToken: t.AccessToken}, nil\n}\n\n// New creates and returns a nodeidentity.Identifier for nodes running on DigitalOcean.\nfunc New(cacheNodeidentityInfo bool) (nodeidentity.Identifier, error) {\n\tregion, err := getMetadataRegion()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get droplet region: %s\", err)\n\t}\n\n\tdoClient, err := NewCloud(region)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to initialize digitalocean cloud: %s\", err)\n\t}\n\n\treturn &nodeIdentifier{\n\t\tdoClient:     doClient,\n\t\tcache:        expirationcache.NewTTLStore(stringKeyFunc, cacheTTL),\n\t\tcacheEnabled: cacheNodeidentityInfo,\n\t}, nil\n}\n\nfunc getMetadataRegion() (string, error) {\n\treturn getMetadata(dropletRegionMetadataURL)\n}\n\n// NewCloud returns a godo client, expecting the env var DIGITALOCEAN_ACCESS_TOKEN to be set.\nfunc NewCloud(region string) (*godo.Client, error) {\n\taccessToken := os.Getenv(\"DIGITALOCEAN_ACCESS_TOKEN\")\n\tif accessToken == \"\" {\n\t\treturn nil, errors.New(\"DIGITALOCEAN_ACCESS_TOKEN is required\")","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodeidentity/do/identify.go#L54-L90","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: systemd unit without token\n[Service]\nExecStart=/usr/local/bin/kops-node-identity\n\n// after\n[Service]\nEnvironmentFile=/etc/kops/do-token\nExecStart=/usr/local/bin/kops-node-identity\n# /etc/kops/do-token: DIGITALOCEAN_ACCESS_TOKEN=dop_v1_xxxx","handlingStrategy":"validation","validationCode":"token := os.Getenv(\"DIGITALOCEAN_ACCESS_TOKEN\")\nif token == \"\" {\n    return fmt.Errorf(\"DIGITALOCEAN_ACCESS_TOKEN must be set before initializing the DO cloud\")\n}\nreq, _ := http.NewRequest(\"GET\", \"https://api.digitalocean.com/v2/account\", nil)\nreq.Header.Set(\"Authorization\", \"Bearer \"+token)\nresp, err := http.DefaultClient.Do(req)\nif err != nil || resp.StatusCode != http.StatusOK {\n    return fmt.Errorf(\"DO token missing or invalid\")\n}","typeGuard":null,"tryCatchPattern":"id, err := nodeidentity.New(true)\nif err != nil && strings.Contains(err.Error(), \"failed to initialize digitalocean cloud\") {\n    return fmt.Errorf(\"check DO API token env/secret: %w\", err)\n}","preventionTips":["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"],"tags":["digitalocean","authentication","api-token","configuration","kops"],"backgroundTag":"missing-api-token","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"}