grafana/k6 · error
token is required to create cloud API client
Error message
token is required to create cloud API client
What it means
cloudapiv6.NewClient refuses to construct a client when the token argument is an empty string — there is no anonymous access to the k6 Cloud v6 API. This is a fail-fast guard at client construction (client.go:31), before any request is made, so hitting it means the caller resolved configuration without a token.
Solutions
- Set the token: `k6 cloud login` (interactive) or export K6_CLOUD_TOKEN, then construct the client
- If calling NewClient directly, resolve the token via the same consolidated config the CLI uses and error out to the user when missing
- In CI, assert the secret is non-empty before invoking k6 (e.g. `test -n "$K6_CLOUD_TOKEN"`)
Example fix
// before
client, err := cloudapiv6.NewClient(logger, os.Getenv("K6_CLOUD_TOKEN"), host, version, timeout)
// after
token := os.Getenv("K6_CLOUD_TOKEN")
if token == "" {
return nil, fmt.Errorf("set K6_CLOUD_TOKEN or run `k6 cloud login`")
}
client, err := cloudapiv6.NewClient(logger, token, host, version, timeout) Defensive patterns
Strategy: validation
Validate before calling
token := strings.TrimSpace(cfg.Token.String)
if token == "" {
return nil, fmt.Errorf("K6_CLOUD_TOKEN not set; run `k6 cloud login`")
} Prevention
- Centralize token resolution in one config loader that fails fast on empty
- In CI, add a guard step: test -n "$K6_CLOUD_TOKEN" || exit 1
- Never construct the v6 client before verifying the login check passes
When it happens
Trigger: Calling NewClient with "" because the token was never read from flags/env/disk config, a K6_CLOUD_TOKEN env var set to empty, or a config loader silently dropping the token field. The cmd layer normally prevents this via checkCloudLogin, so direct API users hit it most.
Common situations: Extensions (xk6) or scripts embedding the cloudapiv6 client without running login first, CI jobs that mask the token to an empty string, or home-dir config files (~/.) removed between login and run.
Related errors
AI-assisted analysis of grafana/k6@8d06114777 (2026-08-18).
Data as JSON: /api/errors/fb94c163dad22762.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cloudapi/v6/client.go:32
"go.k6.io/k6/v2/errext"
"go.k6.io/k6/v2/internal/cloudapi/clientcfg"
"go.k6.io/k6/v2/internal/cloudapi/httperr"
)
// Client handles communication with the k6 Cloud API.
type Client struct {
apiClient *k6cloud.APIClient
token string
stackID int32
baseURL string
logger logrus.FieldLogger
}
// NewClient return a new client for the cloud API
func NewClient(logger logrus.FieldLogger, token, host, version string, timeout time.Duration) (*Client, error) {
if token == "" {
return nil, fmt.Errorf("token is required to create cloud API client")
}
cfg := clientcfg.New(host, version, "Global k6 Cloud API.", timeout)
c := &Client{
apiClient: k6cloud.NewAPIClient(cfg),
token: token,
baseURL: fmt.Sprintf("%s/cloud/v6", host),
logger: logger,
}
return c, nil
}
// SetStackID sets the stack ID for the client. It returns an error if
// stackID does not fit in the int32 range the underlying SDK requires for
// the X-Stack-Id header.
func (c *Client) SetStackID(stackID int64) error {
if stackID < math.MinInt32 || stackID > math.MaxInt32 {View on GitHub (pinned to 8d06114777)