How to fix Playwright "Protocol error (...): invalid argument"?
PlaywrightA "Protocol error: invalid argument" originates from the Chrome DevTools Protocol (CDP) layer and means Playwright sent a command to the browser with a parameter that the browser rejected as unsupported or malformed. This is different from application-level errors — it is a low-level browser API contract violation. Common triggers include passing invalid permission names to context.grantPermissions(), using coordinates outside the viewport for pointer actions, or calling browser-specific APIs on a browser engine that doesn't support them.
Common mistake
test('grants camera access', async ({ browser }) => {
const context = await browser.newContext();
// 'camera' is not a valid Playwright permission string
await context.grantPermissions(['camera']);
const page = await context.newPage();
await page.goto('https://app.example.com/video-call');
});
Another trigger is running Chromium-specific CDP extensions under Firefox or WebKit, which report the CDP command as invalid.
The fix
Use the correct permission names as defined in the Playwright API, and scope permissions to a specific origin:
import { test, expect } from '@playwright/test';
test('requests camera in video call', async ({ browser }) => {
const context = await browser.newContext({
permissions: ['camera', 'microphone'],
});
// Grant permissions for a specific origin
await context.grantPermissions(['camera', 'microphone'], {
origin: 'https://app.example.com',
});
const page = await context.newPage();
await page.goto('https://app.example.com/video-call');
await expect(page.getByText('Camera ready')).toBeVisible();
});
Valid Playwright permission names include: 'geolocation', 'microphone', 'camera', 'notifications', 'clipboard-read', 'clipboard-write'. For browser-specific APIs, gate behavior by project:
import { test } from '@playwright/test';
test('chromium-only CDP feature', async ({ page, browserName }) => {
test.skip(browserName !== 'chromium', 'CDP only available in Chromium');
const client = await page.context().newCDPSession(page);
await client.send('Emulation.setGeolocationOverride', {
latitude: 37.7749,
longitude: -122.4194,
accuracy: 100,
});
});
Why it works
Playwright's permission API maps its strings to CDP Browser.grantPermissions command values. Passing a string that CDP doesn't recognize produces a protocol-level invalid argument rejection before any browser action occurs. Scoping permissions with origin is required by the CDP spec for most permission types — without it, some browsers reject the command. Skipping tests by browserName prevents cross-engine CDP calls that would always produce invalid argument errors.
Tips
- Check the Playwright documentation's permissions list before adding a new permission type — browser support varies and some permissions are Chromium-only.
- If the invalid argument error occurs during a pointer action like click() or hover(), the element may be outside the current viewport — scroll it into view first with locator.scrollIntoViewIfNeeded().
- Protocol errors in CI but not locally often indicate a browser version mismatch — pin your Playwright and browser versions together.
- For crashes tied to protocol errors under memory pressure, see random browser crashes in CI.