kubernetes/kops · critical

DIGITALOCEAN_ACCESS_TOKEN is required

Error message

DIGITALOCEAN_ACCESS_TOKEN is required

What it means

The DigitalOcean bootstrap verifier authenticates incoming kubelet requests against the DO API. NewVerifier reads DIGITALOCEAN_ACCESS_TOKEN from the environment and returns this identical error when it is unset/empty, before any API call is made.

Source

Thrown at upup/pkg/fi/cloudup/do/verifier.go:48

	"golang.org/x/oauth2"
	"k8s.io/kops/pkg/bootstrap"
	"k8s.io/kops/pkg/wellknownports"
	"k8s.io/kops/upup/pkg/fi/cloudup/do/dometadata"
)

type DigitalOceanVerifierOptions struct {
}

type digitalOceanVerifier struct {
	doClient *godo.Client
}

var _ bootstrap.Verifier = (*digitalOceanVerifier)(nil)

func NewVerifier(ctx context.Context, opt *DigitalOceanVerifierOptions) (bootstrap.Verifier, 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})
	doClient := godo.NewClient(oauth2.NewClient(ctx, tokenSource))

	return &digitalOceanVerifier{
		doClient: doClient,
	}, nil
}

func (o digitalOceanVerifier) VerifyToken(ctx context.Context, rawRequest *http.Request, token string, body []byte) (*bootstrap.VerifyResult, error) {
	if !strings.HasPrefix(token, dometadata.DOAuthenticationTokenPrefix) {
		return nil, bootstrap.ErrNotThisVerifier
	}
	serverIDString := strings.TrimPrefix(token, dometadata.DOAuthenticationTokenPrefix)

	serverID, err := strconv.Atoi(serverIDString)
	if err != nil {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Export DIGITALOCEAN_ACCESS_TOKEN in the environment where the verifier runs
  2. Ensure the node bootstrap/manifest passes the token env var into the verifier process
  3. Verify with printenv DIGITALOCEAN_ACCESS_TOKEN that it is non-empty in the target runtime (container/systemd unit)
  4. Use a DO token scoped to read droplets metadata for the verifier

Example fix

// systemd unit before
ExecStart=/usr/local/bin/do-verifier
// after
Environment=DIGITALOCEAN_ACCESS_TOKEN=dop_v1_xxxx
ExecStart=/usr/local/bin/do-verifier
Defensive patterns

Strategy: validation

Validate before calling

if os.Getenv("DIGITALOCEAN_ACCESS_TOKEN") == "" {
	return errors.New("verifier requires DIGITALOCEAN_ACCESS_TOKEN in its runtime environment")
}

Try / catch

v, err := do.NewVerifier(ctx, opts)
if err != nil {
	if err.Error() == "DIGITALOCEAN_ACCESS_TOKEN is required" {
		// inject env var into the verifier's runtime (systemd/container)
	} else { return err }
}

Prevention

When it happens

Trigger: Running a kops-built DigitalOcean verifier binary (used by nodeup/bootstrap on new nodes) in an environment without DIGITALOCEAN_ACCESS_TOKEN set — the main() entry point calls NewVerifier which fails immediately.

Common situations: Bootstrapping new DO nodes where the verifier was run manually without env; container images missing the env var; secrets not mounted into the verifier's runtime environment.

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/805bdaea6bb0c751. Report an issue: GitHub.