{"record":{"id":"5f8c6c601f92e4ee","repo":"jackwener/OpenCLI","slug":"could-not-find-an-add-to-cart-button-on-the-produc","errorCode":null,"errorMessage":"Could not find an add-to-cart button on the product page.","messagePattern":"Could not find an add-to-cart button on the product page\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/coupang/add-to-cart.js","lineNumber":137,"sourceCode":"            throw new CommandExecutionError(`coupang add-to-cart navigation failed: ${error?.message || error}`);\n        });\n        const result = await page.evaluate(buildAddToCartEvaluate(productId)).catch((error) => {\n            throw new CommandExecutionError(`coupang add-to-cart evaluation 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.');\n        }\n        const actualProductId = normalizeProductId(result?.currentProductId || productId);\n        if (result?.reason === 'PRODUCT_MISMATCH') {\n            const observed = actualProductId ? `got ${actualProductId}` : 'no product id observed';\n            throw new CommandExecutionError(`Product mismatch: expected ${productId}, ${observed}`);\n        }\n        if (result?.reason === 'OPTION_REQUIRED') {\n            throw new CommandExecutionError('This product requires option selection and is not supported in v1.');\n        }\n        if (result?.reason === 'ADD_TO_CART_BUTTON_NOT_FOUND') {\n            throw new CommandExecutionError('Could not find an add-to-cart button on the product page.');\n        }\n        if (!result?.ok) {\n            throw new CommandExecutionError('Failed to confirm add-to-cart success.');\n        }\n        return [{\n                ok: true,\n                product_id: actualProductId || productId,\n                url: finalUrl,\n                message: 'Added to cart',\n            }];\n    },\n});\n","sourceCodeStart":119,"sourceCodeEnd":150,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/coupang/add-to-cart.js#L119-L150","documentation":"CommandExecutionError thrown when the in-page script cannot find a clickable add-to-cart button: no button/a[role=button]/input[type=button] whose label matches 장바구니/카트/cart (and is not sold out / 품절). The library aborts rather than clicking blindly.","triggerScenarios":"Product page markup differs from expected selectors — sold-out items, out-of-stock buttons, page loaded in an unexpected language/layout, or Coupang DOM changes renaming cart buttons.","commonSituations":"Product is sold out (button says 품절 and is filtered out); page not fully rendered when evaluate ran; Coupang redesign changed button text/attributes; non-Korean locale serving different labels.","solutions":["Verify the product is in stock (sold-out items are intentionally not clicked)","Add an explicit wait/delay so the page is fully rendered before add-to-cart runs","Check the page in the controlled Chrome browser to see the actual button label/markup","If Coupang changed its DOM, update the button-matching selectors in buildAddToCartEvaluate","Ensure locale/IP serves the standard Korean Coupang layout"],"exampleFix":"// before\n coupang add-to-cart --product-id 12345  # sold out, button says 품절\n// after\n # check availability first\n coupang product --product-id 12345   # confirm in-stock, then retry","handlingStrategy":"retry","validationCode":"const text = await page.evaluate(() => document.body.innerText || '');\nif (/품절|sold out/i.test(text)) {\n  throw new Error(`Product sold out; add-to-cart will fail`);\n}","typeGuard":"function hasAddToCartButton(buttons) {\n  return buttons.some(b => /장바구니|카트|cart/i.test((b.innerText || '') + (b.getAttribute?.('aria-label') || '')) && !/품절|sold out/i.test(b.innerText || ''));\n}","tryCatchPattern":"try {\n  await addToCart(page, productId);\n} catch (err) {\n  if (/add-to-cart button/.test(err.message)) {\n    await page.waitForTimeout(3000);   // let the page finish rendering\n    await addToCart(page, productId);  // retry once\n    return;\n  }\n  throw err;\n}","preventionTips":["Check stock status before attempting add-to-cart","Ensure the page is fully rendered before running the command","Watch for Coupang DOM redesigns that change button labels; pin/monitor selectors","Use a Korean locale/IP so standard Korean button labels are served"],"tags":["coupang","dom-selector","ui-automation"],"backgroundTag":"selector-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}