garrytan/gstack · warning · Error
Usage: browse viewport [<WxH>] [--scale <n>] (e.g. 375x812,
Error message
Usage: browse viewport [<WxH>] [--scale <n>] (e.g. 375x812, or --scale 2 to keep current size)
What it means
Thrown by the `browse viewport` command when it is invoked with no arguments at all. The command requires either a size token (e.g. `375x812`) or a `--scale <n>` flag (or both); when both `sizeArg` and `scaleArg` stay `undefined` after the arg-parsing loop, the command cannot determine what viewport change to make and refuses to proceed. The message is a usage hint pointing the caller to the two accepted forms.
Source
Thrown at browse/src/write-commands.ts:526
if (val === undefined || val === '') {
throw new Error('viewport --scale: missing value. Usage: viewport [WxH] --scale <n>');
}
const parsed = Number(val);
if (!Number.isFinite(parsed)) {
throw new Error(`viewport --scale: value '${val}' is not a finite number.`);
}
scaleArg = parsed;
} else if (args[i].startsWith('--')) {
throw new Error(`Unknown viewport flag: ${args[i]}`);
} else if (sizeArg === undefined) {
sizeArg = args[i];
} else {
throw new Error(`Unexpected positional arg: ${args[i]}. Usage: viewport [WxH] [--scale <n>]`);
}
}
if (sizeArg === undefined && scaleArg === undefined) {
throw new Error('Usage: browse viewport [<WxH>] [--scale <n>] (e.g. 375x812, or --scale 2 to keep current size)');
}
// Resolve width/height: either from sizeArg or from current viewport if --scale-only.
let w: number, h: number;
if (sizeArg) {
if (!sizeArg.includes('x')) throw new Error('Usage: browse viewport [<WxH>] [--scale <n>] (e.g., 375x812)');
const [rawW, rawH] = sizeArg.split('x').map(Number);
w = Math.min(Math.max(Math.round(rawW) || 1280, 1), 16384);
h = Math.min(Math.max(Math.round(rawH) || 720, 1), 16384);
} else {
// --scale without WxH → use BrowserManager's tracked viewport (source of truth
// since setViewport + launchContext keep it in sync). Falls back reliably on
// headed → headless transitions or contexts with viewport:null.
const current = bm.getCurrentViewport();
w = current.width;
h = current.height;
}
View on GitHub (pinned to 94993f7401)
Solutions
- Pass at least one argument: a size token or `--scale <n>` (e.g. `browse viewport 375x812`).
- If you only want to change DPR without resizing, use `browse viewport --scale 2` — the current tracked viewport is reused.
- If you intended to read the current viewport rather than set it, use the read-side command (e.g. `browse info` or the snapshot command) instead of `browse viewport`.
- Inspect the args array your caller is forwarding and ensure it is non-empty before dispatching the command.
Example fix
// before await runBrowseCommand(['viewport']); // after await runBrowseCommand(['viewport', '375x812']); // or await runBrowseCommand(['viewport', '--scale', '2']);
Defensive patterns
Strategy: validation
Validate before calling
function validateViewportArgs(args: string[]): void {
const hasScale = args.includes('--scale');
const hasSize = args.some(a => !a.startsWith('--') && a.includes('x'));
if (!hasScale && !hasSize) {
throw new Error('viewport requires a WxH size or --scale <n>');
}
}
// call before: runBrowseCommand(['viewport', ...args]) Type guard
function isNonEmptyViewportArgs(args: unknown): args is [string, ...string[]] {
return Array.isArray(args) && args.length > 0 && args.every(a => typeof a === 'string');
} Prevention
- Always pass at least one of WxH or --scale to the viewport command.
- When building commands dynamically, assert the args array is non-empty before dispatch.
- Document the two accepted forms in wrapper scripts so callers do not send bare 'viewport'.
When it happens
Trigger: Calling `browse viewport` with an empty args array; calling it with only whitespace tokens that the parser does not classify as a positional; a wrapper script that forwards an unpopulated variable as the viewport payload.
Common situations: An AI agent or shell wrapper builds the viewport command dynamically and the variable holding the dimensions resolves to empty; a user runs `browse viewport` expecting an interactive prompt or a status readout instead of a setter; a typo'd flag like `browse viewport --size 375x812` is consumed as an unknown flag and never sets sizeArg/scaleArg.
Related errors
- Usage: browse viewport [<WxH>] [--scale <n>] (e.g., 375x812)
- Usage: browse cookie <name>=<value>
- 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/068752c695a7c465.
Report an issue: GitHub.