{"record":{"id":"b55eedb798f8b208","repo":"garrytan/gstack","slug":"cannot-use-clip-with-a-selector-ref-choose-one","errorCode":null,"errorMessage":"Cannot use --clip with a selector/ref — choose one","messagePattern":"Cannot use --clip with a selector/ref — choose one","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"browse/src/meta-commands.ts","lineNumber":493,"sourceCode":"        } else if (arg.startsWith('@e') || arg.startsWith('@c') || arg.startsWith('.') || arg.startsWith('#') || arg.includes('[')) {\n          targetSelector = arg;\n        } else {\n          outputPath = arg;\n        }\n      }\n\n      // --selector flag takes precedence; conflict with positional selector.\n      if (flagSelector !== undefined) {\n        if (targetSelector !== undefined) {\n          throw new Error('--selector conflicts with positional selector — choose one');\n        }\n        targetSelector = flagSelector;\n      }\n\n      validateOutputPath(outputPath);\n\n      if (clipRect && targetSelector) {\n        throw new Error('Cannot use --clip with a selector/ref — choose one');\n      }\n      if (viewportOnly && clipRect) {\n        throw new Error('Cannot use --viewport with --clip — choose one');\n      }\n\n      // --base64 mode: capture to buffer instead of disk\n      if (base64Mode) {\n        let buffer: Buffer;\n        if (targetSelector) {\n          const resolved = await bm.resolveRef(targetSelector);\n          const locator = 'locator' in resolved ? resolved.locator : page.locator(resolved.selector);\n          buffer = await locator.screenshot({ timeout: 5000 });\n        } else if (clipRect) {\n          buffer = await page.screenshot({ clip: clipRect });\n        } else {\n          buffer = await page.screenshot({ fullPage: !viewportOnly });\n          // Guard the most common API-bricking case (fullPage). Element /\n          // clip captures usually stay within the cap; we still guard the","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/meta-commands.ts#L475-L511","documentation":"Thrown when `--clip x,y,w,h` and an element target (positional selector or `@ref`, or `--selector`) are both supplied. Playwright cannot capture a clip rectangle AND an element locator simultaneously — they are mutually exclusive capture modes. The guard at lines 492-494 fires before any Playwright call.","triggerScenarios":"`browse screenshot --clip 0,0,100,100 .hero` or `browse screenshot --clip 0,0,100,100 --selector #nav` (lines 492-493).","commonSituations":"Trying to 'crop' an element capture with `--clip`, or copy-pasting a clip invocation and appending a selector for context.","solutions":["Use `--clip` alone to capture a fixed region of the page.","Use a selector/`@ref` alone to capture a specific element (the element's bounding box is used automatically).","If you need a sub-region of an element, capture the element then crop the PNG in post-processing."],"exampleFix":"// before\nbrowse screenshot --clip 0,0,200,200 .hero\n// after\nbrowse screenshot .hero","handlingStrategy":"validation","validationCode":"const hasClip = args.includes('--clip');\nconst hasSelector = args.includes('--selector') ||\n  args.some(a => /^(?:@e|@c|\\.|#|\\[)/.test(a));\nif (hasClip && hasSelector) throw new Error('--clip and selector are mutually exclusive');","typeGuard":null,"tryCatchPattern":"try { await browse.screenshot(args); }\ncatch (err) {\n  if (/Cannot use --clip with a selector/.test(err.message)) {\n    // drop --clip OR the selector and retry based on intent\n  }\n}","preventionTips":["Decide capture mode (element vs region) before building args.","Model the screenshot request as a discriminated union in your wrapper so clip+selector can't coexist."],"tags":["screenshot","argument-parsing","conflict"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}