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
- Use the exact names from the allowlist above, e.g. grantPermissions(['notifications', 'geolocation'])
- Validate your permission array against the allowlist before calling the API
- 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
- Copy permission names from the k6 browser docs allowlist, not Chromium flag strings
- Validate dynamic permission arrays against a Set before granting
- Watch for singular forms ('notification') — they are the most common typo
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
- clearing permissions
- cookie name must be set: %#v
- cookie value must be set: %#v
- default browser context can't be closed
- granting browser permissions
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)