{"record":{"id":"f6ec03ce80f45683","repo":"jackwener/OpenCLI","slug":"product-mismatch-expected-productid-observe","errorCode":null,"errorMessage":"Product mismatch: expected ${productId}, ${observed}","messagePattern":"Product mismatch: expected (.+?), (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/coupang/add-to-cart.js","lineNumber":131,"sourceCode":"        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 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});","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/coupang/add-to-cart.js#L113-L149","documentation":"CommandExecutionError thrown when the in-page evaluation returns reason 'PRODUCT_MISMATCH': the product ID parsed from the URL path (/vp/products/(\\d+)) does not match the --product-id argument the user passed. The library guards against clicking add-to-cart on the wrong product.","triggerScenarios":"Calling add-to-cart with a product-id that differs from the ID of the page actually loaded — e.g. Coupang redirected to a canonical/alternate product page, or the caller passed a stale/mistyped ID.","commonSituations":"Product URL redirects to a different (merged) product; passing the URL of one product with the ID of another; Coupang product ID changed after re-listing; copy-paste error in automation scripts.","solutions":["Compare the expected vs observed product IDs in the message and re-run with the correct --product-id","Omit --product-id and pass only the canonical product --url so the ID is derived from the destination","Check whether Coupang redirects your URL to a different product and use the final URL's ID","If the product was merged/delisted, look up the new product ID on Coupang"],"exampleFix":"// before\n coupang add-to-cart --product-id 11111 --url https://www.coupang.com/vp/products/22222\n// after\n coupang add-to-cart --url https://www.coupang.com/vp/products/22222","handlingStrategy":"validation","validationCode":"const urlId = (url.match(/\\/vp\\/products\\/(\\d+)/) || [])[1];\nif (productId && urlId && productId !== urlId) {\n  throw new Error(`product-id ${productId} does not match url id ${urlId}`);\n}","typeGuard":"function idsMatch(productId, url) {\n  const m = typeof url === 'string' && url.match(/\\/vp\\/products\\/(\\d+)/);\n  return !productId || !m || String(productId) === m[1];\n}","tryCatchPattern":"try {\n  await addToCart(page, productId);\n} catch (err) {\n  if (/Product mismatch/.test(err.message)) {\n    const [, expected, observed] = err.message.match(/expected (\\d+), (.*)/) || [];\n    console.error(`Re-run with observed id: ${observed}`);\n    return;\n  }\n  throw err;\n}","preventionTips":["Derive the product id from the URL rather than passing both independently","Resolve redirects to the final canonical URL before extracting the ID","Re-lookup product IDs after Coupang merges/delists products"],"tags":["coupang","product-mismatch","validation"],"backgroundTag":"product-id-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}