{"record":{"id":"6694ad76332bbed6","repo":"jackwener/OpenCLI","slug":"either-product-id-or-url-is-required-6694ad","errorCode":null,"errorMessage":"Either --product-id or --url is required","messagePattern":"Either --product-id or --url is required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/coupang/product.js","lineNumber":211,"sourceCode":"    name: 'product',\n    access: 'read',\n    description: 'Read full product detail (price, rating, seller, delivery) for a Coupang product',\n    domain: 'www.coupang.com',\n    strategy: Strategy.COOKIE,\n    browser: true,\n    args: [\n        { name: 'product-id', positional: true, required: false, help: 'Coupang product ID (digits only)' },\n        { name: 'url', required: false, help: 'Canonical Coupang product URL (alternative to --product-id)' },\n    ],\n    columns: [\n        'product_id', 'title', 'price', 'original_price', 'discount_rate',\n        'rating', 'review_count', 'seller', 'brand', 'rocket',\n        'delivery_promise', 'image_url', 'url',\n    ],\n    func: async (page, kwargs) => {\n        const rawProductId = kwargs['product-id'];\n        if (!rawProductId && !kwargs.url) {\n            throw new ArgumentError('Either --product-id or --url is required');\n        }\n        const productId = rawProductId\n            ? requireProductIdArg(rawProductId, 'product-id')\n            : requireProductIdArg(kwargs.url, '--url');\n        const targetUrl = canonicalizeProductUrl(kwargs.url, productId);\n        const finalUrl = targetUrl || canonicalizeProductUrl('', productId);\n        await page.goto(finalUrl).catch((error) => {\n            throw new CommandExecutionError(`coupang product navigation failed: ${error?.message || error}`);\n        });\n        await page.wait(2).catch((error) => {\n            throw new CommandExecutionError(`coupang product wait failed: ${error?.message || error}`);\n        });\n        const result = await page.evaluate(buildProductDetailEvaluate(productId)).catch((error) => {\n            throw new CommandExecutionError(`coupang product extraction failed: ${error?.message || error}`);\n        });\n        const loginHints = result?.loginHints ?? {};\n        if (loginHints.hasLoginLink && !loginHints.hasMyCoupang) {\n            throw new AuthRequiredError('coupang.com', 'Please log into Coupang in Chrome and retry.');","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/coupang/product.js#L193-L229","documentation":"ArgumentError thrown by the coupang product command when neither --product-id nor --url is provided. The command needs at least one to identify which Coupang product to fetch; it then validates whichever is given via requireProductIdArg and canonicalizes the target URL.","triggerScenarios":"Invoking 'coupang product' with no arguments, or with misspelled flag names (e.g. --productId instead of --product-id) so kwargs contains neither key.","commonSituations":"Copy-pasting a command and dropping the argument; kebab-case vs camelCase flag confusion; wrapping scripts that fail to forward the argument; empty string passed as --product-id.","solutions":["Pass --product-id <id> with the numeric Coupang product ID","Or pass --url <product-url> and let the CLI extract the ID from the URL","Check flag spelling: must be exactly --product-id or --url (kebab-case)","Verify the value is non-empty — an empty string still triggers the error"],"exampleFix":"// before\n coupang product  # ArgumentError: Either --product-id or --url is required\n// after\n coupang product --url https://www.coupang.com/vp/products/12345678","handlingStrategy":"validation","validationCode":"const productId = process.argv.find(a => a.startsWith('--product-id'))?.split('=')[1];\nconst url = process.argv.find(a => a.startsWith('--url'))?.split('=')[1];\nif (!productId && !url) {\n  throw new Error('Provide --product-id <id> or --url <product-url>');\n}","typeGuard":"function hasProductTarget(kwargs) {\n  return Boolean(kwargs && (typeof kwargs['product-id'] === 'string' && kwargs['product-id'].trim() || typeof kwargs.url === 'string' && kwargs.url.trim()));\n}","tryCatchPattern":"try {\n  await coupangProduct(args);\n} catch (err) {\n  if (err instanceof ArgumentError && /--product-id or --url/.test(err.message)) {\n    console.error('Usage: coupang product --product-id <id> | --url <url>');\n    process.exitCode = 2;\n    return;\n  }\n  throw err;\n}","preventionTips":["Always pass at least one of --product-id or --url","Use exact kebab-case flag names (--product-id, not --productId)","Validate arguments in wrapper scripts before invoking the CLI","Trim/verify values are non-empty strings"],"tags":["argument-validation","cli-usage","coupang"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}