grafana/k6 · error

token is required to create provisioning API client

Error message

token is required to create provisioning API client

What it means

provisioning.NewClient (internal/cloudapi/provisioning/client.go:47) refuses to construct a client without an API token because every provisioning and v6 call uses Bearer auth. An empty token means cloud authentication was never configured, and all subsequent requests would fail with confusing 401s.

Source

Thrown at internal/cloudapi/provisioning/client.go:47

	stackID   int64
	host      string
	version   string

	logger logrus.FieldLogger
}

// NewClient returns a new provisioning Client. It internally constructs
// both a k6cloud.APIClient (for provisioning endpoints) and a v6.Client
// (for v6 operations like FetchTest). The stackID identifies the
// Grafana Cloud stack and is required for the stack-scoped requests.
func NewClient(
	logger logrus.FieldLogger,
	token, host, version string,
	stackID int64,
	timeout time.Duration,
) (*Client, error) {
	if token == "" {
		return nil, fmt.Errorf("token is required to create provisioning API client")
	}

	cfg := clientcfg.New(host, version, "k6 Cloud API (provisioning).", timeout)

	v6c, err := v6.NewClient(logger, token, host, version, timeout)
	if err != nil {
		return nil, fmt.Errorf("creating v6 client: %w", err)
	}

	c := &Client{
		apiClient: k6cloud.NewAPIClient(cfg),
		v6Client:  v6c,
		token:     token,
		stackID:   stackID,
		host:      host,
		version:   version,
		logger:    logger,
	}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Run `k6 cloud login` to store a token, or export K6_CLOUD_TOKEN with a valid API token
  2. If constructing the client in Go, resolve and check the token before calling NewClient
  3. Verify the env var name and that it has no surrounding whitespace/quotes

Example fix

# before
k6 run --local-execution script.js  # no token anywhere

# after
export K6_CLOUD_TOKEN="<api-token>"
k6 run --local-execution script.js
Defensive patterns

Strategy: validation

Validate before calling

token := os.Getenv("K6_CLOUD_TOKEN")
if token == "" {
	return errors.New("K6_CLOUD_TOKEN is empty — run `k6 cloud login` or export the token")
}
client, err := provisioning.NewClient(logger, token, host, version, stackID, timeout)

Type guard

func hasCloudToken(token string) bool { return strings.TrimSpace(token) != "" }

Try / catch

client, err := provisioning.NewClient(logger, token, host, version, stackID, timeout)
if err != nil {
	if strings.Contains(err.Error(), "token is required") {
		// guide the user to login/config, don't surface a raw 401 later
	}
	return err
}

Prevention

When it happens

Trigger: Running cloud / --local-execution flows without `k6 cloud login` and without K6_CLOUD_TOKEN set; constructing provisioning.NewClient programmatically with an empty token string.

Common situations: CI pipelines that forgot to inject the token secret; fresh machines/containers without the k6 Cloud config file; scripts that read the token from an unset variable and pass an empty string.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/4be6d79be7e700aa. Report an issue: GitHub.