jackwener/OpenCLI · error · CommandExecutionError

coupang add-to-cart evaluation failed: ${error?.message || e

Error message

coupang add-to-cart evaluation failed: ${error?.message || error}

What it means

This CommandExecutionError wraps a failure of page.evaluate(buildAddToCartEvaluate(productId)) — i.e. the in-page script that performs add-to-cart threw or could not be evaluated. Common causes inside evaluate: the page DOM isn't what the script expects (selectors missing), the page navigated away mid-evaluation, or an exception raised inside the evaluated function. The library catches it and rethrows with the underlying message.

Source

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

        { name: 'product-id', positional: true, required: false, help: 'Coupang product ID' },
        { name: 'url', required: false, help: 'Canonical product URL' },
    ],
    columns: ['ok', 'product_id', 'url', 'message'],
    func: async (page, kwargs) => {
        const rawProductId = kwargs['product-id'];
        if (!rawProductId && !kwargs.url) {
            throw new ArgumentError('Either --product-id or --url is required');
        }
        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.');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check the wrapped message: 'Execution context was destroyed' means a redirect — add a wait/retry or block navigations during evaluate
  2. Update the library version if Coupang changed their page DOM; the evaluate script may need new selectors
  3. Load the product page manually and verify it's a normal, in-stock product page (not redirecting to sold-out/region error)
  4. Retry the command once — transient hydration timing often causes one-off evaluate failures

Example fix

// before
await page.goto(finalUrl);
const result = await page.evaluate(buildAddToCartEvaluate(productId)); // context destroyed by redirect
// after
await page.goto(finalUrl, { waitUntil: 'networkidle' });
await page.waitForSelector('.prod-atf, #addToCart', { timeout: 15000 });
const result = await page.evaluate(buildAddToCartEvaluate(productId));
Defensive patterns

Strategy: try-catch

Validate before calling

await page.goto(productUrl, { waitUntil: 'networkidle' });
const ready = await page.waitForSelector('.prod-atf, [data-testid="add-to-cart"]', { timeout: 15000 }).catch(() => null);
if (!ready) throw new Error('product page DOM not ready — do not run add-to-cart evaluate yet');

Type guard

function isEvaluateFailure(e) {
  return /add-to-cart evaluation failed|Execution context was destroyed/i.test(e?.message || '');
}

Try / catch

try {
  await runCli('coupang add-to-cart', '--product-id', productId);
} catch (e) {
  if (/Execution context was destroyed/.test(e.message)) {
    // page redirected mid-evaluate: reload and retry once
    return runCli('coupang add-to-cart', '--product-id', productId);
  }
  if (/evaluation failed/.test(e.message)) {
    console.error('DOM may have changed; update the library or inspect the product page');
  }
  throw e;
}

Prevention

When it happens

Trigger: `page.evaluate(...)` rejects after a successful goto: Execution context destroyed by a client-side redirect on the product page, an uncaught exception in buildAddToCartEvaluate's DOM logic (e.g. add-to-cart button/app state missing), or the page being navigated/closed during evaluation.

Common situations: Coupang changing their product-page DOM so the injected script's selectors throw, the product page auto-redirecting (sold out, region block) destroying the execution context, slow page load where the script runs before the app hydrates, or an out-of-stock item whose UI path errors.

Related errors


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