{"record":{"id":"475786249c851e63","repo":"jackwener/OpenCLI","slug":"failed-to-fetch-quote-for-symbol-475786","errorCode":null,"errorMessage":"Failed to fetch quote for ${symbol}","messagePattern":"Failed to fetch quote for (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/yahoo-finance/quote.js","lineNumber":71,"sourceCode":"        const titleEl = document.querySelector('title');\n        const priceEl = document.querySelector('[data-testid=\"qsp-price\"]');\n        const changeEl = document.querySelector('[data-testid=\"qsp-price-change\"]');\n        const changePctEl = document.querySelector('[data-testid=\"qsp-price-change-percent\"]');\n        if (priceEl) {\n          return {\n            symbol: sym,\n            name: titleEl ? titleEl.textContent.split('(')[0].trim() : sym,\n            price: priceEl.textContent.replace(/,/g, ''),\n            change: changeEl ? changeEl.textContent : null,\n            changePercent: changePctEl ? changePctEl.textContent : null,\n            open: null, high: null, low: null, volume: null, marketCap: null,\n          };\n        }\n        return {error: 'Could not fetch quote for ' + sym};\n      })()\n    `);\n        if (!data || data.error)\n            throw new CommandExecutionError(data?.error || `Failed to fetch quote for ${symbol}`);\n        return [data];\n    },\n});\n","sourceCodeStart":53,"sourceCodeEnd":75,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/yahoo-finance/quote.js#L53-L75","documentation":"The yahoo-finance quote command tries two strategies inside the page: the v8 chart API and DOM scraping of the quote page ([data-testid=\"qsp-price\"]). If both fail, the page.evaluate returns {error: 'Could not fetch quote for SYM'} (or null) and the wrapper throws CommandExecutionError. The library throws this because it could not obtain any price data for the requested ticker — usually the symbol does not exist, was delisted, or Yahoo served a page without the expected markup.","triggerScenarios":"Calling `yahoo-finance quote <SYMBOL>` where the v8 chart API returns non-ok or empty chart.result AND the quote page has no qsp-price element — invalid/delisted ticker, Yahoo consent/anti-bot page, or Yahoo DOM redesign breaking the selectors.","commonSituations":"Typo in ticker symbol (e.g. lowercase handled, but nonexistent like 'ZZZZZ'); delisted or OTC symbol not on Yahoo; Yahoo showing GDPR/consent interstitial; Yahoo changed their page markup so data-testid selectors no longer match; query1 API blocked (429).","solutions":["Verify the ticker symbol exists on finance.yahoo.com and retry with the correct symbol","Open the finance.yahoo.com quote page in the CLI browser and complete any consent/captcha interstitial, then retry","Retry later if Yahoo rate-limited the v8 chart API (429)","If the DOM selectors are outdated, update the [data-testid=...] selectors to Yahoo's current markup"],"exampleFix":"// before\nawait page.goto(`https://finance.yahoo.com/quote/${symbol}/`);\nconst data = await page.evaluate(...); // both strategies fail for bad symbol\n// after (pre-validate symbol via chart API status)\nconst resp = await fetch(`https://query1.finance.yahoo.com/v8/finance/chart/${symbol}?interval=1d&range=1d`);\nif (resp.status === 404) throw new CommandExecutionError(`Unknown symbol: ${symbol}`);","handlingStrategy":"validation","validationCode":"if (!/^[A-Z0-9.\\-]{1,10}$/i.test(symbol)) throw new Error(`Invalid ticker format: ${symbol}`);","typeGuard":"function isQuoteData(d) { return d != null && typeof d === 'object' && !('error' in d) && d.price != null; }","tryCatchPattern":"try {\n  const [quote] = await yahooQuote(symbol);\n} catch (e) {\n  if (e instanceof CommandExecutionError && e.message.includes('fetch quote')) {\n    return { error: 'QUOTE_UNAVAILABLE', symbol, hint: 'Verify the ticker exists on finance.yahoo.com' };\n  }\n  throw e;\n}","preventionTips":["Validate ticker symbols against a known list or the Yahoo search API before quoting","Handle consent/GDPR interstitials by completing them once in the browser profile","Keep selectors ([data-testid=...]) in sync with Yahoo's current markup","Retry the v8 chart API with backoff when it is rate-limited (429)"],"tags":["yahoo-finance","scraping","invalid-symbol","dom-selector"],"backgroundTag":"scrape-target-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}