grafana/k6 · error · ErrNotAuthorized

not allowed to upload result to k6 Cloud

Error message

not allowed to upload result to k6 Cloud

What it means

Frame.IsDisabled() (frame.go:1488) wraps the isDisabled action failure as 'checking is %q disabled'. The action waits for a selector match in the attached state within Timeout and queries the element's 'disabled' state with a zero timeout (the state itself is not waited on). Wrapped errors are selector timeouts, strict-mode violations, frame/context destruction during the check, or failures of the injected state script.

Source

Thrown at internal/cloudapi/httperr/httperr.go:17

// Package httperr contains HTTP-status-code error helpers shared by k6
// Cloud's API clients (cloudapi, internal/cloudapi/v6). It only covers the
// part of their CheckResponse-style functions that's genuinely identical
// across them - classifying 401/403 - everything else about decoding an
// error response body differs between API versions.
package httperr

import (
	"errors"
	"net/http"
)

var (
	// ErrNotAuthenticated maps HTTP 401.
	ErrNotAuthenticated = errors.New("failed to authenticate with k6 Cloud")
	// ErrNotAuthorized maps HTTP 403.
	ErrNotAuthorized = errors.New("not allowed to upload result to k6 Cloud")
)

// ClassifyStatus returns ErrNotAuthenticated for HTTP 401, ErrNotAuthorized
// for HTTP 403, and nil for any other status code.
func ClassifyStatus(statusCode int) error {
	switch statusCode {
	case http.StatusUnauthorized:
		return ErrNotAuthenticated
	case http.StatusForbidden:
		return ErrNotAuthorized
	default:
		return nil
	}
}

View on GitHub (pinned to 01ffac6f24)

Solutions

  1. Wait for the element first: await page.waitForSelector(sel, { state: 'attached', timeout: 10000 }).
  2. Narrow the selector (data-testid) to avoid strict-mode violations.
  3. Run the check on the correct frame.
  4. Increase timeout for slow pages: page.isDisabled(sel, { timeout: 60000 }).

Example fix

// before
const off = await page.isDisabled('#submit');

// after
const btn = page.locator('#submit');
await btn.waitFor({ state: 'attached', timeout: 10000 });
const off = await btn.isDisabled();
Defensive patterns

Strategy: try-catch

Validate before calling

const btn = page.locator('#submit');
await btn.waitFor({ state: 'attached', timeout: 5000 });

Try / catch

try {
  return await page.isDisabled(sel, { timeout: 10000 });
} catch (e) {
  if (String(e).includes('timed out')) throw new Error(`element never appeared: ${sel}`);
  throw e;
}

Prevention

When it happens

Trigger: No element matches before opts.Timeout; Strict:true with multiple matches; frame navigates/detaches during the check; injected script errors on non-standard elements.

Common situations: Asserting buttons are disabled during in-flight requests; fields inside lazily mounted modals; using the main frame object for iframe content; broad selectors matching many nodes under strict mode.

Related errors


AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18). Data as JSON: /api/errors/d55aad8903fe05a8. Report an issue: GitHub.