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

  1. Provide the token as `name=value`: `browse cookie sessionid=abc123`.
  2. 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).
  3. If you wanted to set a header instead, use `browse header name:value`.
  4. 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

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


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