{"record":{"id":"884f4746af85f653","repo":"jackwener/OpenCLI","slug":"amazon-product-expects-an-asin-or-product-url","errorCode":null,"errorMessage":"amazon product expects an ASIN or product URL","messagePattern":"amazon product expects an ASIN or product URL","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/amazon/shared.js","lineNumber":145,"sourceCode":"    const match = normalized.match(/\\/(?:dp|gp\\/product|product-reviews)\\/([A-Z0-9]{10})/i);\n    return match ? match[1].toUpperCase() : null;\n}\nexport function amazonHostFromInput(input) {\n    const normalized = cleanText(input);\n    if (!normalized)\n        return null;\n    try {\n        const url = new URL(normalized);\n        return isAmazonMarketplaceHost(url.hostname) ? url.hostname : null;\n    }\n    catch {\n        return null;\n    }\n}\nexport function buildProductUrl(input) {\n    const asin = extractAsin(input);\n    if (!asin) {\n        throw new ArgumentError('amazon product expects an ASIN or product URL', 'Example: opencli amazon product B0FJS72893');\n    }\n    const host = amazonHostFromInput(input);\n    return host ? `https://${host}/dp/${asin}` : `${PRODUCT_URL_PREFIX}${asin}`;\n}\nexport function buildDiscussionUrl(input) {\n    const asin = extractAsin(input);\n    if (!asin) {\n        throw new ArgumentError('amazon discussion expects an ASIN or product URL', 'Example: opencli amazon discussion B0FJS72893');\n    }\n    const host = amazonHostFromInput(input);\n    return host ? `https://${host}/product-reviews/${asin}` : `${DISCUSSION_URL_PREFIX}${asin}`;\n}\nfunction getRankingSpec(listType) {\n    return AMAZON_RANKING_SPECS[listType];\n}\nexport function isSupportedRankingPath(listType, inputUrl) {\n    try {\n        const url = new URL(inputUrl);","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/amazon/shared.js#L127-L163","documentation":"An ArgumentError thrown by buildProductUrl when the input contains neither a valid 10-character ASIN nor a recognizable Amazon product URL (extractAsin returned null). The library cannot construct a /dp/ product link without an ASIN, so it fails fast with usage guidance.","triggerScenarios":"Passing a random string, a truncated URL missing the /dp/<ASIN> segment, an ASIN with wrong length/characters, or an empty input to `amazon product`, or to any call chain through productUrl/normalizeProductUrl.","commonSituations":"User pastes a shortened amzn.to link; a non-Amazon URL (eBay, another store); an 11-character or lowercase-invalid ID; copying only part of the product URL.","solutions":["Pass a valid 10-character ASIN, e.g. B0FJS72893","Paste the full Amazon product URL containing /dp/<ASIN>","Verify you copied the ASIN from the product page and not a review or offer ID"],"exampleFix":"// before\nopencli amazon product 'https://amzn.to/3xYz'\n// after\nopencli amazon product B0FJS72893","handlingStrategy":"validation","validationCode":"const ASIN_RE = /^B?[0-9A-Z]{9,10}$/;\nif (!ASIN_RE.test(input ?? '')) throw new Error(`'${input}' is not a valid ASIN`);","typeGuard":"const isAsin = (v) => typeof v === 'string' && /^[0-9A-Z]{10}$/.test(v.trim());","tryCatchPattern":"try {\n  const url = buildProductUrl(input);\n} catch (err) {\n  if (err.message.includes('expects an ASIN or product URL')) {\n    // prompt user for a valid ASIN or full /dp/ URL\n  } else throw err;\n}","preventionTips":["Copy the 10-character ASIN directly from the product page","Prefer full /dp/<ASIN> URLs over shorteners like amzn.to","Validate ASIN format (10 alphanumerics) before calling","Avoid pasting review or offer links"],"tags":["validation","asin","bad-input"],"backgroundTag":"invalid-asin-input","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}