garrytan/gstack · warning · Error
Usage: browse cookie <name>=<value>
Error message
Usage: browse cookie <name>=<value>
What it means
Thrown by `browse cookie` when the first argument is missing or does not contain an `=` character. The command parses a single `name=value` token by splitting on the first `=`; without that separator it cannot derive a cookie name and refuses to write a cookie whose name would be the entire string with an empty value.
Source
Thrown at browse/src/write-commands.ts:557
// headed → headless transitions or contexts with viewport:null.
const current = bm.getCurrentViewport();
w = current.width;
h = current.height;
}
if (scaleArg !== undefined) {
const err = await bm.setDeviceScaleFactor(scaleArg, w, h);
if (err) return `Viewport partially set: ${err}`;
return `Viewport set to ${w}x${h} @ ${scaleArg}x (context recreated; refs and load-html content replayed)`;
}
await bm.setViewport(w, h);
return `Viewport set to ${w}x${h}`;
}
case 'cookie': {
const cookieStr = args[0];
if (!cookieStr || !cookieStr.includes('=')) throw new Error('Usage: browse cookie <name>=<value>');
const eq = cookieStr.indexOf('=');
const name = cookieStr.slice(0, eq);
const value = cookieStr.slice(eq + 1);
const url = new URL(page.url());
await page.context().addCookies([{
name,
value,
domain: url.hostname,
path: '/',
}]);
return `Cookie set: ${name}=****`;
}
case 'header': {
const headerStr = args[0];
if (!headerStr || !headerStr.includes(':')) throw new Error('Usage: browse header <name>:<value>');
const sep = headerStr.indexOf(':');
const name = headerStr.slice(0, sep).trim();View on GitHub (pinned to 94993f7401)
Solutions
- Provide the token as `name=value`: `browse cookie sessionid=abc123`.
- Quote the whole token if the value contains characters the shell would split on: `browse cookie "token=a=b=c"` (only the FIRST `=` is used as the separator, so embedded `=` in the value is preserved).
- If you wanted to set a header instead, use `browse header name:value`.
- For bulk import including domain/path/expiry, use `browse cookie-import <file>` instead of setting one cookie at a time.
Example fix
// before await runBrowseCommand(['cookie', 'sessionid:abc123']); // after await runBrowseCommand(['cookie', 'sessionid=abc123']);
Defensive patterns
Strategy: validation
Validate before calling
function parseCookieToken(token: string): { name: string; value: string } {
if (!token || !token.includes('=')) {
throw new Error('cookie token must be name=value');
}
const eq = token.indexOf('=');
return { name: token.slice(0, eq), value: token.slice(eq + 1) };
} Type guard
function isCookieToken(s: string): boolean {
return typeof s === 'string' && s.includes('=') && s.indexOf('=') > 0;
} Prevention
- Use '=' as the separator for cookies and ':' for headers — they are distinct commands.
- Quote the token if the value contains characters the shell would split on.
- Only the first '=' is the separator, so values may contain '='.
When it happens
Trigger: Calling `browse cookie` with no args; `browse cookie sessionid` (value omitted); `browse cookie sessionid:abc123` (wrong separator, a `:` leftover from header-style usage); quoting that strips the `=` when the shell splits the token.
Common situations: User conflates the cookie command (`name=value`) with the header command (`name:value`); an agent forwards a value that already URL-encoded the `=`; copy-pasting a `Set-Cookie:` header line that contains attributes after the first `;` works but the user assumed it would not and pre-trimmed at the wrong character.
Related errors
- Usage: browse cookie-import <json-file>
- Usage: browse viewport [<WxH>] [--scale <n>] (e.g. 375x812,
- Usage: browse header <name>:<value>
- Usage: browse useragent <string>
- Usage: browse upload <selector> <file1> [file2...]
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/14820ea22f169f18.
Report an issue: GitHub.