garrytan/gstack · error · Error
Each cookie must have "name" and "value" fields
Error message
Each cookie must have "name" and "value" fields
What it means
Thrown by `browse cookie-import` inside the per-cookie validation loop when a cookie object lacks a `name` field or has `value === undefined`. Playwright's `addCookies` requires both, so the command rejects the entire batch on the first malformed entry rather than letting Playwright throw an opaque error mid-import. Note `value: ''` (empty string) is accepted — only `undefined` is rejected.
Source
Thrown at browse/src/write-commands.ts:668
try { resolvedReal = fs.realpathSync(resolved); } catch {
// File may not exist yet — resolve parent dir instead
try { resolvedReal = path.join(fs.realpathSync(path.dirname(resolved)), path.basename(resolved)); } catch {}
}
if (!SAFE_DIRECTORIES.some(dir => isPathWithin(resolvedReal, dir))) {
throw new Error(`Path must be within: ${SAFE_DIRECTORIES.join(', ')}`);
}
if (!fs.existsSync(filePath)) throw new Error(`File not found: ${filePath}`);
const raw = fs.readFileSync(filePath, 'utf-8');
let cookies: any[];
try { cookies = JSON.parse(raw); } catch (err: any) { throw new Error(`Invalid JSON in ${filePath}: ${err?.message || err}`); }
if (!Array.isArray(cookies)) throw new Error('Cookie file must contain a JSON array');
// Auto-fill domain from current page URL when missing (consistent with cookie command)
const pageUrl = new URL(page.url());
const defaultDomain = pageUrl.hostname;
for (const c of cookies) {
if (!c.name || c.value === undefined) throw new Error('Each cookie must have "name" and "value" fields');
if (!c.domain) {
c.domain = defaultDomain;
} else {
const cookieDomain = c.domain.startsWith('.') ? c.domain.slice(1) : c.domain;
if (cookieDomain !== defaultDomain && !defaultDomain.endsWith('.' + cookieDomain)) {
throw new Error(`Cookie domain "${c.domain}" does not match current page domain "${defaultDomain}". Use the target site first.`);
}
}
if (!c.path) c.path = '/';
}
await page.context().addCookies(cookies);
const importedDomains = [...new Set(cookies.map((c: any) => c.domain).filter(Boolean))];
if (importedDomains.length > 0) bm.trackCookieImportDomains(importedDomains);
return `Loaded ${cookies.length} cookies from ${filePath}`;
}
case 'cookie-import-browser': {View on GitHub (pinned to 94993f7401)
Solutions
- Ensure each cookie object has both `name` (truthy string) and `value` (defined, may be empty string) fields.
- If your source uses different keys, map them: `cookies.map(c => ({ name: c.cookie_name, value: c.cookie_value ?? '', domain: c.domain, path: c.path }))`.
- Validate the array shape before importing: every element must be an object with `name` and `value`.
- Use Playwright's own `context.cookies()` export as the canonical shape reference.
Example fix
// before
const cookies = [{ name: 'sid' }, { name: 'csrf', value: 'abc' }];
fs.writeFileSync(fp, JSON.stringify(cookies));
await runBrowseCommand(['cookie-import', fp]);
// after
const cookies = [{ name: 'sid', value: 'x', domain: 'example.com', path: '/' }, { name: 'csrf', value: 'abc', domain: 'example.com', path: '/' }];
fs.writeFileSync(fp, JSON.stringify(cookies));
await runBrowseCommand(['cookie-import', fp]); Defensive patterns
Strategy: type-guard
Validate before calling
function validateCookieShape(cookies: unknown[]): void {
cookies.forEach((c, i) => {
if (typeof c !== 'object' || c === null || !('name' in c) || !('value' in c) || (c as any).value === undefined) {
throw new Error(`cookies[${i}] must have name and value fields`);
}
});
} Type guard
function isCookieObject(v: unknown): v is { name: string; value: string; domain?: string; path?: string } {
return typeof v === 'object' && v !== null && typeof (v as any).name === 'string' && (v as any).name.length > 0 && 'value' in v && (v as any).value !== undefined;
} Prevention
- Map source fields to {name, value} before importing.
- Note empty-string value is allowed; only undefined is rejected.
- Validate the array shape before passing to cookie-import.
When it happens
Trigger: A cookie object shaped as `{ name: 'x' }` (value missing), `{ value: 'y' }` (name missing), `{ n: 'x', v: 'y' }` (wrong keys from a Netscape column mapping), or a string element in the array instead of an object.
Common situations: Export tool used different field names (`cookie_name` vs `name`); a Netscape-to-JSON converter mapped columns wrong; a hand-built cookie array omitted `value` for flag-only cookies; an LLM-generated cookie JSON used `"value"` as the key but left it null.
Related errors
- Usage: browse cookie-import <json-file>
- File not found: ${filePath}
- Invalid JSON in ${filePath}: ${err?.message || err}
- Cookie domain "${c.domain}" does not match current page doma
- --domain "${domain}" does not match current page domain "${p
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/bb11ff76e1ff3281.
Report an issue: GitHub.