grafana/k6 · error

is an invalid permission

Error message

%q is an invalid permission

What it means

GrantPermissions maps friendly permission strings to CDP PermissionType values before issuing Browser.grantPermissions; the given string is not in the allowlist. Names accepted by this build: geolocation, midi, midi-sysex, notifications, camera, microphone, background-sync, ambient-light-sensor, accelerometer, gyroscope, magnetometer, clipboard-read, clipboard-write, payment-handler. The check is client-side, so nothing reaches the browser.

Solutions

  1. Use the exact names from the allowlist above, e.g. grantPermissions(['notifications', 'geolocation'])
  2. Validate your permission array against the allowlist before calling the API
  3. Check for accidental concatenation — pass an array of separate strings

Example fix

// before
ctx.grantPermissions(['notification', 'clipboardReadWrite']); // both invalid

// after
ctx.grantPermissions(['notifications', 'clipboard-read', 'clipboard-write']);
Defensive patterns

Strategy: validation

Validate before calling

const VALID_PERMISSIONS = new Set([
  'geolocation', 'midi', 'midi-sysex', 'notifications',
  'camera', 'microphone', 'background-sync', 'ambient-light-sensor',
  'accelerometer', 'gyroscope', 'magnetometer',
  'clipboard-read', 'clipboard-write', 'payment-handler',
]);
function assertValidPermissions(perms) {
  for (const p of perms) {
    if (!VALID_PERMISSIONS.has(p)) {
      throw new Error(`invalid permission '${p}'; allowed: ${[...VALID_PERMISSIONS].join(', ')}`);
    }
  }
}
assertValidPermissions(['notifications', 'geolocation']);
ctx.grantPermissions(['notifications', 'geolocation']);

Type guard

const isPermissionName = (p) => typeof p === 'string' && VALID_PERMISSIONS.has(p);

Prevention

When it happens

Trigger: browserContext.grantPermissions(['notification']) (singular), Chromium raw names like 'clipboardReadWrite' or 'sensors', empty strings, or a comma-joined string 'geolocation,camera' instead of an array element.

Common situations: Typos and singular/plural mistakes; copying permission names from Chromium flag strings or other tools' docs instead of the k6/Playwright list; building the array dynamically from unvalidated config.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at internal/js/modules/k6/browser/common/browser_context.go:243

		"midi-sysex":           cdpbrowser.PermissionTypeMidiSysex,
		"notifications":        cdpbrowser.PermissionTypeNotifications,
		"camera":               cdpbrowser.PermissionTypeVideoCapture,
		"microphone":           cdpbrowser.PermissionTypeAudioCapture,
		"background-sync":      cdpbrowser.PermissionTypeBackgroundSync,
		"ambient-light-sensor": cdpbrowser.PermissionTypeSensors,
		"accelerometer":        cdpbrowser.PermissionTypeSensors,
		"gyroscope":            cdpbrowser.PermissionTypeSensors,
		"magnetometer":         cdpbrowser.PermissionTypeSensors,
		"clipboard-read":       cdpbrowser.PermissionTypeClipboardReadWrite,
		"clipboard-write":      cdpbrowser.PermissionTypeClipboardSanitizedWrite,
		"payment-handler":      cdpbrowser.PermissionTypePaymentHandler,
	}

	perms := make([]cdpbrowser.PermissionType, 0, len(permissions))
	for _, p := range permissions {
		proto, ok := permsToProtocol[p]
		if !ok {
			return fmt.Errorf("%q is an invalid permission", p)
		}
		perms = append(perms, proto)
	}

	action := cdpbrowser.GrantPermissions(perms).WithOrigin(opts.Origin).WithBrowserContextID(b.id)
	if err := action.Do(cdp.WithExecutor(b.ctx, b.browser.conn)); err != nil {
		return fmt.Errorf("granting browser permissions: %w", err)
	}

	return nil
}

// NewPage creates a new page inside this browser context.
func (b *BrowserContext) NewPage() (*Page, error) {
	b.logger.Debugf("BrowserContext:NewPage", "bctxid:%v", b.id)
	_, span := TraceAPICall(b.ctx, "", "browserContext.newPage")
	defer span.End()

View on GitHub (pinned to 01ffac6f24)