{"record":{"id":"9d02d34296825218","repo":"jackwener/OpenCLI","slug":"spec-invalidinputmessage","errorCode":null,"errorMessage":"spec.invalidInputMessage","messagePattern":"spec\\.invalidInputMessage","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/amazon/shared.js","lineNumber":186,"sourceCode":"    }\n}\nexport function resolveRankingUrl(listType, input) {\n    const spec = getRankingSpec(listType);\n    const normalized = cleanText(input);\n    if (!normalized || normalized === 'root')\n        return spec.rootUrl;\n    let candidateUrl;\n    if (normalized.startsWith('/')) {\n        candidateUrl = new URL(normalized, HOME_URL).toString();\n    }\n    else if (/^https?:\\/\\//i.test(normalized)) {\n        candidateUrl = canonicalizeAmazonUrl(normalized);\n    }\n    else if (normalized.includes('amazon.') && normalized.includes('/')) {\n        candidateUrl = canonicalizeAmazonUrl(`https://${normalized.replace(/^\\/+/, '')}`);\n    }\n    else {\n        throw new ArgumentError(spec.invalidInputMessage, spec.invalidInputHint);\n    }\n    if (!isSupportedRankingPath(listType, candidateUrl)) {\n        throw new ArgumentError(spec.invalidInputMessage, spec.invalidInputHint);\n    }\n    return normalizeRankingInputUrl(candidateUrl);\n}\nfunction normalizeRankingInputUrl(inputUrl) {\n    try {\n        const url = new URL(inputUrl);\n        const normalizedPathSegments = url.pathname\n            .split('/')\n            .filter(Boolean)\n            .filter((segment) => !/^ref=/i.test(segment));\n        url.pathname = `/${normalizedPathSegments.join('/')}`;\n        url.hash = '';\n        // Ranking pages are frequently shared with tracking refs that can land on unstable variants.\n        // Dropping ref keeps the canonical ranking path while preserving useful params (for example pg=2).\n        url.searchParams.delete('ref');","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/amazon/shared.js#L168-L204","documentation":"An ArgumentError thrown by resolveRankingUrl when the normalized input is neither a canonical Amazon URL nor a bare amazon.* host+path, i.e. the string cannot be resolved into a ranking URL for the given list type (spec). The spec-specific invalidInputMessage/hint describe the expected format for that ranking command.","triggerScenarios":"Calling resolveRankingUrl with a non-URL string (e.g. a category name), a URL without 'amazon.' in it, or a bare host with no path where a full URL is required by the branch logic.","commonSituations":"User passes 'electronics' instead of a URL; passes 'amazon.com/bestsellers' without scheme but with trailing characters the branch doesn't match; wrapping tool passes an encoded or mangled URL.","solutions":["Pass a full https Amazon URL for the ranking page","Use the documented shorthand (bare ASIN/category URL) per the command's --url help","Check the input isn't a category name — look up the category URL instead"],"exampleFix":"// before\nopencli amazon bestsellers --url 'electronics'\n// after\nopencli amazon bestsellers --url 'https://www.amazon.com/Best-Sellers-Electronics/zgbs/electronics'","handlingStrategy":"validation","validationCode":"const looksLikeUrl = (s) => typeof s === 'string' && /^(https?:\\/\\/)?[\\w.-]*amazon\\.[\\w.]+\\/\\S+/.test(s.trim());\nif (!looksLikeUrl(rankingInput)) throw new Error(`'${rankingInput}' is not an Amazon URL`);","typeGuard":null,"tryCatchPattern":"try {\n  const url = resolveRankingUrl(input, spec);\n} catch (err) {\n  if (err.message === spec.invalidInputMessage) {\n    // show spec.invalidInputHint to the user\n  } else throw err;\n}","preventionTips":["Pass full https Amazon URLs for ranking commands","Don't pass bare category names","Follow the spec's invalidInputHint format","URL-encode only path segments, not the whole URL"],"tags":["validation","url-parsing"],"backgroundTag":"invalid-url-input","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}