kubernetes/kops · critical

DIGITALOCEAN_ACCESS_TOKEN is required

Error message

DIGITALOCEAN_ACCESS_TOKEN is required

What it means

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.

Source

Thrown at upup/pkg/fi/cloudup/do/cloud.go:104

// static compile time check to validate DOCloud's fi.Cloud Interface.
var _ fi.Cloud = (*doCloudImplementation)(nil)

// doCloudImplementation holds the godo client object to interact with DO resources.
type doCloudImplementation struct {
	Client *godo.Client

	dns dnsprovider.Interface

	// region holds the DO region.
	region string
}

// NewDOCloud returns a Cloud, expecting the env var DIGITALOCEAN_ACCESS_TOKEN
// NewDOCloud will return an err if DIGITALOCEAN_ACCESS_TOKEN is not defined
func NewDOCloud(region string) (DOCloud, error) {
	accessToken := os.Getenv("DIGITALOCEAN_ACCESS_TOKEN")
	if accessToken == "" {
		return nil, errors.New("DIGITALOCEAN_ACCESS_TOKEN is required")
	}

	tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: accessToken})
	client := godo.NewClient(oauth2.NewClient(context.TODO(), tokenSource))

	return &doCloudImplementation{
		Client: client,
		dns:    dns.NewProvider(client),
		region: region,
	}, nil
}

func (c *doCloudImplementation) GetCloudGroups(cluster *kops.Cluster, instancegroups []*kops.InstanceGroup, warnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error) {
	return getCloudGroups(c, cluster, instancegroups, warnUnmatched, nodes)
}

// DeleteGroup is not implemented yet, is a func that needs to delete a DO instance group.
func (c *doCloudImplementation) DeleteGroup(g *cloudinstances.CloudInstanceGroup) error {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. export DIGITALOCEAN_ACCESS_TOKEN=<your-token> before running kops
  2. Generate a Personal Access Token in the DigitalOcean console if you don't have one (with read/write scopes)
  3. Check the value is non-empty: [ -n "$DIGITALOCEAN_ACCESS_TOKEN" ] && echo set
  4. In CI, add the token as a secret env var to the job

Example fix

// before (shell)
kops update cluster mycluster.k8s.local --yes
// after
export DIGITALOCEAN_ACCESS_TOKEN="dop_v1_xxxx"
kops update cluster mycluster.k8s.local --yes
Defensive patterns

Strategy: validation

Validate before calling

if os.Getenv("DIGITALOCEAN_ACCESS_TOKEN") == "" {
	return fmt.Errorf("DIGITALOCEAN_ACCESS_TOKEN must be exported before invoking kops on DigitalOcean")
}

Try / catch

_, err := do.NewDOCloud(region)
if err != nil {
	if err.Error() == "DIGITALOCEAN_ACCESS_TOKEN is required" {
		// prompt user / fail fast with instructions
	} else { return err }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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