{"record":{"id":"28f28ba45a2da74a","repo":"kubernetes/kops","slug":"digitalocean-access-token-is-required-28f28b","errorCode":null,"errorMessage":"DIGITALOCEAN_ACCESS_TOKEN is required","messagePattern":"DIGITALOCEAN_ACCESS_TOKEN is required","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"upup/pkg/fi/cloudup/do/cloud.go","lineNumber":104,"sourceCode":"// static compile time check to validate DOCloud's fi.Cloud Interface.\nvar _ fi.Cloud = (*doCloudImplementation)(nil)\n\n// doCloudImplementation holds the godo client object to interact with DO resources.\ntype doCloudImplementation struct {\n\tClient *godo.Client\n\n\tdns dnsprovider.Interface\n\n\t// region holds the DO region.\n\tregion string\n}\n\n// NewDOCloud returns a Cloud, expecting the env var DIGITALOCEAN_ACCESS_TOKEN\n// NewDOCloud will return an err if DIGITALOCEAN_ACCESS_TOKEN is not defined\nfunc NewDOCloud(region string) (DOCloud, error) {\n\taccessToken := os.Getenv(\"DIGITALOCEAN_ACCESS_TOKEN\")\n\tif accessToken == \"\" {\n\t\treturn nil, errors.New(\"DIGITALOCEAN_ACCESS_TOKEN is required\")\n\t}\n\n\ttokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: accessToken})\n\tclient := godo.NewClient(oauth2.NewClient(context.TODO(), tokenSource))\n\n\treturn &doCloudImplementation{\n\t\tClient: client,\n\t\tdns:    dns.NewProvider(client),\n\t\tregion: region,\n\t}, nil\n}\n\nfunc (c *doCloudImplementation) GetCloudGroups(cluster *kops.Cluster, instancegroups []*kops.InstanceGroup, warnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error) {\n\treturn getCloudGroups(c, cluster, instancegroups, warnUnmatched, nodes)\n}\n\n// DeleteGroup is not implemented yet, is a func that needs to delete a DO instance group.\nfunc (c *doCloudImplementation) DeleteGroup(g *cloudinstances.CloudInstanceGroup) error {","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/do/cloud.go#L86-L122","documentation":"NewDOCloud builds the DigitalOcean cloud client from the DIGITALOCEAN_ACCESS_TOKEN environment variable, which is the only supported credential source; if the variable is empty or unset it refuses to construct the client.","triggerScenarios":"Running kops against a DigitalOcean cluster (BuildCloud path) without exporting DIGITALOCEAN_ACCESS_TOKEN, or with it set to an empty string in the shell/CI environment.","commonSituations":"CI pipelines where the secret was not injected; switching shells and losing the exported var; typo like DIGITAL_OCEAN_ACCESS_TOKEN; using a .env file that is not sourced.","solutions":["export DIGITALOCEAN_ACCESS_TOKEN=<your-token> before running kops","Generate a Personal Access Token in the DigitalOcean console if you don't have one (with read/write scopes)","Check the value is non-empty: [ -n \"$DIGITALOCEAN_ACCESS_TOKEN\" ] && echo set","In CI, add the token as a secret env var to the job"],"exampleFix":"// before (shell)\nkops update cluster mycluster.k8s.local --yes\n// after\nexport DIGITALOCEAN_ACCESS_TOKEN=\"dop_v1_xxxx\"\nkops update cluster mycluster.k8s.local --yes","handlingStrategy":"validation","validationCode":"if os.Getenv(\"DIGITALOCEAN_ACCESS_TOKEN\") == \"\" {\n\treturn fmt.Errorf(\"DIGITALOCEAN_ACCESS_TOKEN must be exported before invoking kops on DigitalOcean\")\n}","typeGuard":null,"tryCatchPattern":"_, err := do.NewDOCloud(region)\nif err != nil {\n\tif err.Error() == \"DIGITALOCEAN_ACCESS_TOKEN is required\" {\n\t\t// prompt user / fail fast with instructions\n\t} else { return err }\n}","preventionTips":["Always export DIGITALOCEAN_ACCESS_TOKEN in shell profiles or CI job env","Source .env files before running kops commands","Check env early in scripts: : \"${DIGITALOCEAN_ACCESS_TOKEN:?must be set}\"","Avoid variable name typos (single word, underscores)"],"tags":["digitalocean","authentication","env-var","credentials"],"backgroundTag":"missing-env-var","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"}