Skip to content

Keep looking for a favicon when the home page can't be read - #5422

Open
dave-atx wants to merge 1 commit into
Ranchero-Software:mainfrom
dave-atx:favicon-home-page-fallback
Open

dave-atx wants to merge 1 commit into
Ranchero-Software:mainfrom
dave-atx:favicon-home-page-fallback

Conversation

@dave-atx

@dave-atx dave-atx commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

fixes #5421

findFaviconURLs returned nil whenever cachedMetadata did, so a feed whose home page couldn't be fetched got no favicon at all -- for as long as the failure record lasted, 11 days after a 4xx. But the last candidate it appends, scheme://host/favicon.ico, needs no HTML to find.

cachedMetadata returns nil in two different situations: the download is still in flight, or it isn't coming. Only the first is worth waiting for. HTMLMetadataDownloader now tracks the second and answers metadataIsUnavailable, posting htmlMetadataAvailable so existing observers re-query.

Sync accounts feel this most, since Miniflux, Feedly, ReaderAPI and local accounts never set iconURL or faviconURL -- those are JSON-Feed-only -- so scraping the home page is their only route to an icon. Hacker News is a good example: it declares only y18.svg, which we filter, leaving favicon.ico as the sole candidate.

Also fixes the verdict that suppresses future lookups. currentHomePageHasOnlyFaviconICO was one flag, written when candidates were built and read later, asynchronously, once some home page ran out of them. Different home pages interleave, so it often belonged to a different site than the one being finalized. It's now a set keyed by home page, and a transient failure -- which SingleFaviconDownloader reports as a nil error -- no longer counts as an answer about the site.

Candidate assembly moves to a pure faviconCandidates function, which makes the decision table testable. Adds an ImagesTests target, the first for this module.

findFaviconURLs returned nil whenever cachedMetadata did, so a feed whose home
page couldn't be fetched got no favicon at all -- for as long as the failure
record lasted, 11 days after a 4xx. But the last candidate it appends,
scheme://host/favicon.ico, needs no HTML to find.

cachedMetadata returns nil in two different situations: the download is still
in flight, or it isn't coming. Only the first is worth waiting for.
HTMLMetadataDownloader now tracks the second and answers metadataIsUnavailable,
posting htmlMetadataAvailable so existing observers re-query.

Sync accounts feel this most, since Miniflux, Feedly, ReaderAPI and local
accounts never set iconURL or faviconURL -- those are JSON-Feed-only -- so
scraping the home page is their only route to an icon. Hacker News is a good
example: it declares only y18.svg, which we filter, leaving favicon.ico as the
sole candidate.

Also fixes the verdict that suppresses future lookups.
currentHomePageHasOnlyFaviconICO was one flag, written when candidates were
built and read later, asynchronously, once some home page ran out of them.
Different home pages interleave, so it often belonged to a different site than
the one being finalized. It's now a set keyed by home page, and a transient
failure -- which SingleFaviconDownloader reports as a nil error -- no longer
counts as an answer about the site.

Candidate assembly moves to a pure faviconCandidates function, which makes the
decision table testable. Adds an ImagesTests target, the first for this module.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dave-atx
dave-atx force-pushed the favicon-home-page-fallback branch from 30ac118 to e332dcd Compare September 9, 2026 01:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A feed loses its favicon for good when its home page's HTML metadata fetch fails

1 participant