{"record":{"id":"068752c695a7c465","repo":"garrytan/gstack","slug":"usage-browse-viewport-wxh-scale-n-e-g","errorCode":null,"errorMessage":"Usage: browse viewport [<WxH>] [--scale <n>]  (e.g. 375x812, or --scale 2 to keep current size)","messagePattern":"Usage: browse viewport \\[<WxH>\\] \\[--scale <n>\\]  \\(e\\.g\\. 375x812, or --scale 2 to keep current size\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"browse/src/write-commands.ts","lineNumber":526,"sourceCode":"          if (val === undefined || val === '') {\n            throw new Error('viewport --scale: missing value. Usage: viewport [WxH] --scale <n>');\n          }\n          const parsed = Number(val);\n          if (!Number.isFinite(parsed)) {\n            throw new Error(`viewport --scale: value '${val}' is not a finite number.`);\n          }\n          scaleArg = parsed;\n        } else if (args[i].startsWith('--')) {\n          throw new Error(`Unknown viewport flag: ${args[i]}`);\n        } else if (sizeArg === undefined) {\n          sizeArg = args[i];\n        } else {\n          throw new Error(`Unexpected positional arg: ${args[i]}. Usage: viewport [WxH] [--scale <n>]`);\n        }\n      }\n\n      if (sizeArg === undefined && scaleArg === undefined) {\n        throw new Error('Usage: browse viewport [<WxH>] [--scale <n>]  (e.g. 375x812, or --scale 2 to keep current size)');\n      }\n\n      // Resolve width/height: either from sizeArg or from current viewport if --scale-only.\n      let w: number, h: number;\n      if (sizeArg) {\n        if (!sizeArg.includes('x')) throw new Error('Usage: browse viewport [<WxH>] [--scale <n>] (e.g., 375x812)');\n        const [rawW, rawH] = sizeArg.split('x').map(Number);\n        w = Math.min(Math.max(Math.round(rawW) || 1280, 1), 16384);\n        h = Math.min(Math.max(Math.round(rawH) || 720, 1), 16384);\n      } else {\n        // --scale without WxH → use BrowserManager's tracked viewport (source of truth\n        // since setViewport + launchContext keep it in sync). Falls back reliably on\n        // headed → headless transitions or contexts with viewport:null.\n        const current = bm.getCurrentViewport();\n        w = current.width;\n        h = current.height;\n      }\n","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/write-commands.ts#L508-L544","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait runBrowseCommand(['viewport']);\n\n// after\nawait runBrowseCommand(['viewport', '375x812']);\n// or\nawait runBrowseCommand(['viewport', '--scale', '2']);","handlingStrategy":"validation","validationCode":"function validateViewportArgs(args: string[]): void {\n  const hasScale = args.includes('--scale');\n  const hasSize = args.some(a => !a.startsWith('--') && a.includes('x'));\n  if (!hasScale && !hasSize) {\n    throw new Error('viewport requires a WxH size or --scale <n>');\n  }\n}\n// call before: runBrowseCommand(['viewport', ...args])","typeGuard":"function isNonEmptyViewportArgs(args: unknown): args is [string, ...string[]] {\n  return Array.isArray(args) && args.length > 0 && args.every(a => typeof a === 'string');\n}","tryCatchPattern":null,"preventionTips":["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'."],"tags":["cli-usage","viewport","argument-validation","browse-command"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}