From 99b51bf24d44e09119c745981d8e35bdb856f629 Mon Sep 17 00:00:00 2001 From: Chris Fiel Date: Thu, 28 May 2026 15:53:03 +0800 Subject: [PATCH] Fix yahoo-finance search for US-listed ETFs with options chains Yahoo Finance's /v1/finance/search endpoint returns OPTION and FUTURE quoteTypes alongside the requested EQUITY/ETF row. yahoo-finance2's SearchQuoteYahoo* schemas don't include those quoteTypes, so AJV rejects the entire payload and the search() call throws. Ghostfolio's YahooFinanceService.search() returns an empty array, breaking symbol lookup in the Add Activity dialog for any US-listed ETF with an active options chain (IXUS, VTI, IVV, VOO, QQQM, SCHF, VIG, etc.). The downstream quoteTypes.includes(quoteType) filter already excludes OPTION rows, so disabling strict response validation here is safe and preserves all existing behavior. --- CHANGELOG.md | 37 ++----------------- .../yahoo-finance/yahoo-finance.service.ts | 26 ++++++++++++- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87da5e0bd..0ce88891e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `nestjs` from version `11.1.19` to `11.1.21` +### Fixed + +- Fixed the symbol lookup for US-listed ETFs with active options chains (e.g. `IXUS`, `VTI`, `IVV`, `VOO`, `QQQM`, `SCHF`, `VIG`) by disabling strict AJV validation on the Yahoo Finance search response (Yahoo returns `OPTION`/`FUTURE` quoteTypes that `yahoo-finance2`'s schemas reject, causing the entire payload to be discarded; the downstream `quoteType` filter already excludes options) + ## 3.5.0 - 2026-05-24 ### Added @@ -23,39 +27,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed the deprecated `api/v1/order` endpoints - Upgraded `@keyv/redis` from version `4.4.0` to `5.1.6` -### Fixed - -- Fixed a layout regression that caused a double scrollbar on pages without tabs -- Resolved an issue with missing cash positions caused by an incorrect data source - -## 3.4.0 - 2026-05-21 - -### Added - -- Added the icon column to the benchmark component -- Added support for the `DIRECT_URL` environment variable to enable direct database connections - -### Changed - -- Improved the pagination in the activities table of the account detail dialog -- Improved the pagination in the activities table of the holding detail dialog -- Randomized the placeholder in the assistant -- Filtered out sectors with zero weight for ETF and mutual fund assets in the _Yahoo Finance_ data enhancer -- Enabled the _Bull Dashboard_ in the admin control panel without requiring an environment variable (experimental) -- Improved the verification of the _Stripe_ checkout session when creating a subscription -- Relaxed the URL validation in the asset profile DTOs to accept both `HTTP` and `HTTPS` protocols -- Relaxed the URL validation in the platform DTOs to accept both `HTTP` and `HTTPS` protocols -- Extracted the page tabs to a reusable component -- Improved the language localization for German (`de`) -- Improved the language localization for Spanish (`es`) -- Upgraded `bull-board` from version `7.0.0` to `7.1.5` -- Upgraded `Nx` from version `22.7.1` to `22.7.2` - -### Fixed - -- Resolved an issue with the cash balance calculation of an account for `SELL` activities to ensure fees are correctly subtracted -- Resolved an exception in the portfolio details endpoint when an asset profile is unmatched - ## 3.3.0 - 2026-05-14 ### Added diff --git a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts index de8807098..a6f9f99c4 100644 --- a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts +++ b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts @@ -37,7 +37,10 @@ import { Price, QuoteSummaryResult } from 'yahoo-finance2/esm/src/modules/quoteSummary'; -import { SearchQuoteNonYahoo } from 'yahoo-finance2/esm/src/modules/search'; +import { + SearchQuoteNonYahoo, + SearchResult +} from 'yahoo-finance2/esm/src/modules/search'; @Injectable() export class YahooFinanceService implements DataProviderInterface { @@ -252,7 +255,26 @@ export class YahooFinanceService implements DataProviderInterface { quoteTypes.push('INDEX'); } - const searchResult = await this.yahooFinance.search(query); + // Yahoo's /v1/finance/search returns OPTION/FUTURE quoteTypes alongside + // EQUITY/ETF, but yahoo-finance2's SearchQuoteYahoo* schemas don't list + // OPTION, so AJV rejects the entire payload and the search call throws. + // The library still parses the JSON and attaches it to `error.result` — + // catch and fall back to it, mirroring the pattern used for the + // `quote()` call below. The downstream `quoteTypes.includes(quoteType)` + // filter excludes OPTION rows from the user-facing results. + // Symptoms in the UI without this fix: typing any US-listed ETF with + // an active options chain (IXUS, VTI, IVV, VOO, QQQM, SCHF, VIG, ...) + // returns nothing in the Add Activity dropdown except CoinGecko + // fuzzy matches. + let searchResult: SearchResult = { quotes: [] } as SearchResult; + + try { + searchResult = await this.yahooFinance.search(query); + } catch (error) { + if (error?.result) { + searchResult = error.result; + } + } const quotes = searchResult.quotes .filter(