jackwener/OpenCLI · error · CommandExecutionError

Product mismatch: expected ${productId}, ${observed}

Error message

Product mismatch: expected ${productId}, ${observed}

What it means

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.

Source

Thrown at clis/coupang/add-to-cart.js:131

        const productId = rawProductId
            ? requireProductIdArg(rawProductId, 'product-id')
            : requireProductIdArg(kwargs.url, '--url');
        const targetUrl = canonicalizeProductUrl(kwargs.url, productId);
        const finalUrl = targetUrl || canonicalizeProductUrl('', productId);
        await page.goto(finalUrl).catch((error) => {
            throw new CommandExecutionError(`coupang add-to-cart navigation failed: ${error?.message || error}`);
        });
        const result = await page.evaluate(buildAddToCartEvaluate(productId)).catch((error) => {
            throw new CommandExecutionError(`coupang add-to-cart evaluation failed: ${error?.message || error}`);
        });
        const loginHints = result?.loginHints ?? {};
        if (loginHints.hasLoginLink && !loginHints.hasMyCoupang) {
            throw new AuthRequiredError('coupang.com', 'Please log into Coupang in Chrome and retry.');
        }
        const actualProductId = normalizeProductId(result?.currentProductId || productId);
        if (result?.reason === 'PRODUCT_MISMATCH') {
            const observed = actualProductId ? `got ${actualProductId}` : 'no product id observed';
            throw new CommandExecutionError(`Product mismatch: expected ${productId}, ${observed}`);
        }
        if (result?.reason === 'OPTION_REQUIRED') {
            throw new CommandExecutionError('This product requires option selection and is not supported in v1.');
        }
        if (result?.reason === 'ADD_TO_CART_BUTTON_NOT_FOUND') {
            throw new CommandExecutionError('Could not find an add-to-cart button on the product page.');
        }
        if (!result?.ok) {
            throw new CommandExecutionError('Failed to confirm add-to-cart success.');
        }
        return [{
                ok: true,
                product_id: actualProductId || productId,
                url: finalUrl,
                message: 'Added to cart',
            }];
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Compare the expected vs observed product IDs in the message and re-run with the correct --product-id
  2. Omit --product-id and pass only the canonical product --url so the ID is derived from the destination
  3. Check whether Coupang redirects your URL to a different product and use the final URL's ID
  4. If the product was merged/delisted, look up the new product ID on Coupang

Example fix

// before
 coupang add-to-cart --product-id 11111 --url https://www.coupang.com/vp/products/22222
// after
 coupang add-to-cart --url https://www.coupang.com/vp/products/22222
Defensive patterns

Strategy: validation

Validate before calling

const urlId = (url.match(/\/vp\/products\/(\d+)/) || [])[1];
if (productId && urlId && productId !== urlId) {
  throw new Error(`product-id ${productId} does not match url id ${urlId}`);
}

Type guard

function idsMatch(productId, url) {
  const m = typeof url === 'string' && url.match(/\/vp\/products\/(\d+)/);
  return !productId || !m || String(productId) === m[1];
}

Try / catch

try {
  await addToCart(page, productId);
} catch (err) {
  if (/Product mismatch/.test(err.message)) {
    const [, expected, observed] = err.message.match(/expected (\d+), (.*)/) || [];
    console.error(`Re-run with observed id: ${observed}`);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/f6ec03ce80f45683. Report an issue: GitHub.