Make WordPress Core

Opened 6 months ago

Closed 4 months ago

Last modified 4 months ago

#65098 closed defect (bug) (fixed)

get_site_icon_url() returns empty string even when fallback is defined, breaking wp-embed-site-icon in the_embed_site_title()

Reported by: pontocinza Owned by: westonruter
Priority: normal Milestone: 7.1
Component: Embeds Version: 4.3
Severity: normal Keywords: has-patch has-test-info commit has-unit-tests
Cc: Focuses:

Description (last modified by sabernhardt)

In wp-includes/embed.php, the function the_embed_site_title() calls
get_site_icon_url() twice, passing a fallback URL as the second argument:

    esc_url( get_site_icon_url( 32, includes_url( 'images/w-logo-blue.png' ) ) ),
    esc_url( get_site_icon_url( 64, includes_url( 'images/w-logo-blue.png' ) ) ),

Despite a Site Icon being properly defined in Appearance → Customize → Site
Identity (a 512×512px image), get_site_icon_url() returns an empty string,
ignoring the fallback entirely. This results in a broken icon in all oEmbed
cards rendered via the_embed_site_title().

The generated HTML is:

    <img src="" srcset=" 2x" width="32" height="32" alt="" class="wp-embed-site-icon">

Note that src is empty and srcset contains only 2x, which causes
browsers to interpret it as a relative URL request to /embed/2x, returning
a 403 error.

The WordPress logo fallback (w-logo-blue.png) is also never used, contrary
to the documented behavior of get_site_icon_url().

Steps to reproduce

  1. Set a Site Icon in Appearance → Customize → Site Identity (512×512px image)
  2. Create a post
  3. On another page, add a Media & Text block or an Embed block pointing to that post's URL
  4. Visit the page — the site icon in the oEmbed card footer will be broken
  5. Inspect the element: src="" and srcset=" 2x"

Expected behavior

The site icon should display correctly, or — if unavailable — the WordPress
logo fallback (w-logo-blue.png) should be used instead.

Actual behavior

get_site_icon_url() returns an empty string regardless of the defined icon
or fallback, producing a malformed <img> tag with empty src and srcset.

Workaround

The following filter removes the broken icon from the embed footer:

    add_filter('embed_site_title_html', function($site_title) {
        return preg_replace('/<img[^>]+class="wp-embed-site-icon"[^>]*>/i', '', $site_title);
    });

Environment

  • WordPress 6.9.4
  • PHP (production server)
  • Site Icon defined, 512×512px, uploaded via Customizer
  • APCu object cache active
  • Cloudflare in front of the site

Attachments (2)

bug-2026-04-18_133557.webp​ (36.1 KB ) - added by pontocinza 6 months ago.
bug-2026-04-18_155647.webp​ (30.4 KB ) - added by pontocinza 6 months ago.

Download all attachments as: .zip

Change History (21)

#1 @sabernhardt
6 months ago

  • Description modified (diff)
  • Keywords needs-patch added
  • Milestone Awaiting Review → 7.1
  • Version 6.9.4

Hi and welcome to WordPress Core Trac!

I think you might have a plugin or theme that uses the get_site_icon_url filter. I can break the site icon image in embeds by adding this to a custom plugin:

add_filter( 'get_site_icon_url', '__return_empty_string' );

The filter runs at the end of the get_site_icon_url() function, so the fallback WordPress logo would not override that.

The atom_site_icon() and wp_site_icon() functions check the value before trying to print it, and a similar condition probably could fit the_embed_site_title().

function atom_site_icon() {
	$url = get_site_icon_url( 32 );
	if ( $url ) {
		echo '<icon>' . convert_chars( $url ) . "</icon>\n";
	}
}
function wp_site_icon() {
	if ( ! has_site_icon() && ! is_customize_preview() ) {
		return;
	}

	$meta_tags = array();
	$icon_32   = get_site_icon_url( 32 );
	if ( empty( $icon_32 ) && is_customize_preview() ) {
		$icon_32 = '/favicon.ico'; // Serve default favicon URL in customizer so element can be updated for preview.
	}
	if ( $icon_32 ) {
		$meta_tags[] = sprintf( '<link rel="icon" href="%s" sizes="32x32" />', esc_url( $icon_32 ) );
	}

#2 @sabernhardt
6 months ago

Other functions:

  • site_icon_url(), do_favicon() and the multisite function wp_admin_bar_my_sites_menu() also use output from get_site_icon_url() without checking the value first. (correction: the admin toolbar checks if has_site_icon())
  • WP_REST_Server::add_site_icon_to_index() assigns a URL from get_site_icon_url(), but I do not know if that is a (potential) problem.
Last edited 4 months ago by sabernhardt (previous) (diff)

#3 follow-up: @pontocinza
6 months ago

Thank you for the diagnosis.

The active theme is Twenty Twenty (unmodified). I reviewed the plugin list, and none of them are SEO, favicon, or icon-related plugins that would typically use 'get_site_icon_url'. I also fully reviewed the source code of my own custom SEO plugin, which does not touch that filter. WPCode snippets were checked; nothing related to site icon or favicon. The custom CSS only covers layout, typography, and logo sizing. No interference with icons.

Additionally, I can pinpoint when the issue started: it appeared today, after I replaced a PNG for a WebP image (and it was not the site icon file). Before that change, the embed icon was displaying correctly. No plugins were added, removed, or modified around that time.

This suggests the problem may be triggered by WebP format support (or lack thereof) in one of the functions you listed rather than a filter returning an empty string.

Could this be investigated from the Core side? The defensive check you proposed for 'the_embed_site_title()' still seems like the right fix, but the root cause in my case appears to be format-related, not filter-related.

#4 @mohamedahamed
6 months ago

Yes, the defensive checks needs to be added in Core, namely:

  1. In get_site_icon_url() (general-template.php): Only update $url if the attachment URL is not empty
  1. In the_embed_site_title() (embed.php): Check if URL is empty before rendering the img tag (like wp_site_icon() already does).

This ticket was mentioned in ​PR #11601 on ​WordPress/wordpress-develop by ​@sukhendu2002.


6 months ago
#5

  • Keywords has-patch added; needs-patch removed

… fails

Trac ticket: https://core.trac.wordpress.org/ticket/65098

## Use of AI Tools

#6 in reply to: ↑ 3 ; follow-up: @sabernhardt
6 months ago

Additionally, I can pinpoint when the issue started: it appeared today, after I replaced a PNG for a WebP image (and it was not the site icon file).

In February, the site icon image was pontocinza300.png, which is no longer at the same URL. If that was deleted or renamed, the site_icon option would not be removed automatically. I noticed that you updated the site icon image to pontocinza512.webp since opening this ticket, and that icon displays for me now, at least in the browser tab (your site does not allow embedding posts in a different site).

the problem may be triggered by WebP format support (or lack thereof)

I did not have trouble in an embedded post or browser tab when I set a WebP image as the icon in my site (Windows 11 with Chrome, Firefox and Edge). However, browser support for WebP as a favicon might not be good enough yet. ​Edge and ​Google forums have reports from last year about WebP not displaying correctly.

#7 in reply to: ↑ 6 @pontocinza
6 months ago

Replying to sabernhardt:

Additionally, I can pinpoint when the issue started: it appeared today, after I replaced a PNG for a WebP image (and it was not the site icon file).

In February, the site icon image was pontocinza300.png, which is no longer at the same URL. If that was deleted or renamed, the site_icon option would not be removed automatically. I noticed that you updated the site icon image to pontocinza512.webp since opening this ticket, and that icon displays for me now, at least in the browser tab (your site does not allow embedding posts in a different site).


I don't remember when I started to use 'pontocinza512.webp' as the site icon; it was a long time ago. I've tried to solve the issue by removing the site icon and reinstating the very same file again, but of course it didn't work.

the problem may be triggered by WebP format support (or lack thereof)

I did not have trouble in an embedded post or browser tab when I set a WebP image as the icon in my site (Windows 11 with Chrome, Firefox and Edge). However, browser support for WebP as a favicon might not be good enough yet. ​Edge and ​Google forums have reports from last year about WebP not displaying correctly.


I'm a heavy user of PngOut and Tweakpng and love the PNG format, but I have very few remaining PNG files in my site.

#8 @abcd95
6 months ago

  • Keywords has-test-info added

Test Report

Description

This report validates whether the indicated patch works as expected.
Patch tested: ​https://github.com/WordPress/wordpress-develop/pull/11601

Environment

  • WordPress: 7.1-alpha-62161-src
  • PHP: 8.3.30
  • Server: nginx/1.29.8
  • Database: mysqli (Server: 8.4.8 / Client: mysqlnd 8.3.30)
  • Browser: Chrome 147.0.0.0
  • OS: macOS
  • Theme: Twenty Twenty-Five 1.4

Reproduction Steps

  1. Created a test post ("Test Embed Post") and visited /?p={postID}&embed=true
  2. Simulated broken get_site_icon_url() via add_filter( 'get_site_icon_url', 'return_empty_string' )
  3. Confirmed bug: <img src="" srcset=" 2x"> in the embed footer
  4. Applied patch from PR #11601
  5. Re-tested the same embed URL

Actual Results

✅ The issue is resolved after applying the patch.

Supplemental Artifacts

Before patch

https://i.ibb.co/Y7vF0mhc/Screenshot-2026-04-21-at-22-49-06.png

After patch

https://i.ibb.co/XrdB3Stg/Screenshot-2026-04-21-at-22-48-04.png

#9 @pontocinza
6 months ago

Where is the like button? =)

​@westonruter commented on ​PR #11601:


6 months ago
#10

Can we add tests for get_site_icon_url() and the_embed_site_title() to cover the new code paths?

I see there are existing tests for get_site_icon_url() in tests/phpunit/tests/general/template.php but I don't see existing coverage for the_embed_site_title().

#11 @westonruter
6 months ago

  • Keywords needs-unit-tests added

#12 @manhar
6 months ago

Tested the patch successfully. The site icon now displays correctly in oEmbed cards instead of showing a broken image. The fallback to wp-logo-blue.png also works as expected when the icon is unavailable. The malformed srcset issue is also resolved.

#13 @westonruter
6 months ago

  • Keywords commit added
  • Owner set to westonruter
  • Status new → reviewing

This ticket was mentioned in ​PR #11652 on ​WordPress/wordpress-develop by ​@dhrupo.


6 months ago
#14

  • Keywords has-unit-tests added; needs-unit-tests removed

## Summary
When a site icon option is set but wp_get_attachment_image_url() cannot resolve a URL, the provided fallback URL should be preserved instead of being replaced with false.

## Testing Instructions

  1. Set the site_icon option to an invalid attachment ID.
  2. Call get_site_icon_url( 32, "https://example.org/fallback.png" ).
  3. Confirm the fallback URL is returned.
  4. Run npm run test:php -- --filter test_get_site_icon_url.

#15 follow-up: @rollybueno
4 months ago

I was not able to reproduce the issue on my end.

One thing I noticed is that Site Identity is not available under Appearance → Customize when using the latest Twenty Twenty-Five theme in my test environment. I was able to find Customize, but its pretty much the Editor experience, and I could not find a Site Identity section there.

Instead, I added the site icon through:

Settings → General → Site Icon and used 512x512

After that, I followed the remaining reproduction steps. The site icon did not appear broken in the oEmbed card footer. The generated markup contains valid src and srcset values:

<img src="http://localhost:8889/wp-content/uploads/2026/06/cropped-e6a784a1-a750-4796-9c67-cb476401f19a-1-32x32.jpeg" srcset="http://localhost:8889/wp-content/uploads/2026/06/cropped-e6a784a1-a750-4796-9c67-cb476401f19a-1-150x150.jpeg 2x" width="32" height="32" alt="" class="wp-embed-site-icon">

Tested on the latest develop branch with the following environment:

  • WordPress: 7.1-alpha-62161-src
  • Subdirectory: No
  • PHP: 8.2.29
  • Server: nginx/1.29.4
  • Database: mysqli (Server: 8.4.8 / Client: mysqlnd 8.2.29)
  • Browser: Chrome 149.0.0.0
  • OS: Linux
  • Theme: Twenty Twenty-Five 1.5
  • MU Plugins: None activated
  • Plugins:
    • Test Reports 1.3.0

​@westonruter commented on ​PR #11601:


4 months ago
#16

Double-checking this.

With the following plugin code in place:

add_filter( 'wp_get_attachment_image_src', '__return_false' );

When accessing a post that has another post embedded:

Before:

https://github.com/user-attachments/assets/71b3dc44-e982-4f85-8778-d32166444204

After:

https://github.com/user-attachments/assets/06347943-f7e5-4388-ac66-407498695a46

So it's working well for me.

#17 in reply to: ↑ 15 @westonruter
4 months ago

Replying to rollybueno:

I was not able to reproduce the issue on my end.

I wasn't able to reproduce the issue either using the reproduction steps, but I was able to reproduce it by adding this PHP filter code:

<?php
add_filter( 'wp_get_attachment_image_src', '__return_false' );

In any case, this makes the code more resilient to when the assigned site icon image fails to be retrieved in get_site_icon_url() and wp_get_attachment_image_url( $site_icon_id, $size_data ) returns false, which it is documented as a valid return value.

#18 @westonruter
4 months ago

  • Version → 4.3

#19 @westonruter
4 months ago

  • Resolution → fixed
  • Status reviewing → closed

In 62502:

Embeds: Preserve the site icon fallback URL.

Previously, get_site_icon_url() overwrote a caller-supplied fallback URL with the return value of wp_get_attachment_image_url() even when that lookup returned false, so a defined fallback (such as the bundled WordPress logo) was silently discarded whenever the assigned site icon attachment could not be resolved. Only update the URL when a non-empty attachment URL is returned.

Additionally, the_embed_site_title() now renders the site icon <img> only when a URL is available, and omits the srcset attribute when the 2x URL is missing or identical to the 1x URL. This avoids the malformed markup (an empty src and a bare 2x srcset) that produced a broken image and spurious requests in oEmbed cards.

Developed in ​https://github.com/WordPress/wordpress-develop/pull/11601.
Follow-up to r35571, r36693, r47832.

Props sukhendu2002, sabernhardt, mukesh27, westonruter, pontocinza, mohamedahamed, abcd95, manhar, rollybueno.
Fixes #65098.

Note: See TracTickets for help on using tickets.