grafana/k6 · error
granting browser permissions
Error message
granting browser permissions: %w
What it means
The permission names were valid, but the CDP command Browser.grantPermissions failed for this context/origin. The wrapped error carries Chromium's reason: malformed origin, unknown browser context ID, or a transport failure. Nothing is partially granted — the command is atomic per call.
Solutions
- Pass origin with an explicit scheme: { origin: 'https://example.com' }, or omit it to grant for all origins
- Grant permissions right after creating the context, before any page work and before close
- Read the wrapped CDP message — it distinguishes bad origin from closed context
- If policy blocks the permission (camera/mic on locked-down images), remove it from the list or use an image that allows it
Example fix
// before
ctx.grantPermissions(['geolocation'], { origin: 'example.com' }); // malformed origin
// after
ctx.grantPermissions(['geolocation'], { origin: 'https://example.com' }); Defensive patterns
Strategy: validation
Validate before calling
// origins must include a scheme; validate before granting
function isValidOrigin(o) {
return o === undefined || /^https?:\/\/[\w.-]+(:\d+)?$/.test(o);
}
const origin = 'https://example.com';
if (isValidOrigin(origin)) {
ctx.grantPermissions(['geolocation'], { origin });
} Try / catch
try {
ctx.grantPermissions(perms, { origin });
} catch (e) {
if (String(e.message).includes('granting browser permissions')) {
// inspect e for the CDP reason: bad origin vs closed context vs dead browser
throw new Error(`grant failed: ${e.message}`);
}
throw e;
} Prevention
- Always pass origin as 'https://host' including the scheme
- Grant permissions right after newContext, before pages and before any close
- On locked-down CI images, avoid camera/microphone grants
When it happens
Trigger: grantPermissions(perms, { origin: 'example.com' }) without a scheme; granting on a context that was already closed; granting while the browser connection is down; headless shells or enterprise policies refusing camera/microphone grants.
Common situations: Origin passed as bare hostname instead of 'https://example.com'; permissions code running in teardown after context disposal; CI environments where policy blocks sensitive permissions.
Related errors
- clearing permissions
- adding init script to browser context
- can't fetch the page for unknown reason
- cannot set cookies
- capturing screenshot
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/039857a7e31e2a31.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/browser_context.go:250
"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()
p, err := b.browser.newPageInContext(b.id)
if err != nil {
return nil, spanRecordErrorf(span, "creating new page in browser context: %w", err)
}
b.logger.Debugf("BrowserContext:NewPage:return", "bctxid:%v ptid:%s", b.id, p.targetID)
return p, nilView on GitHub (pinned to 01ffac6f24)