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

  1. Ensure each cookie object has both `name` (truthy string) and `value` (defined, may be empty string) fields.
  2. 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 }))`.
  3. Validate the array shape before importing: every element must be an object with `name` and `value`.
  4. 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

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


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/bb11ff76e1ff3281. Report an issue: GitHub.