Make WordPress Core

Opened 10 hours ago

#66429 new defect (bug)

Fonts: theme.json font loading failures are silent even with WP_DEBUG enabled

Reported by: manucastle78 Owned by:
Priority: normal Milestone: Awaiting Review
Component: Themes Version: trunk
Severity: normal Keywords: dev-feedback
Cc: Focuses:

Description

When a font declared in theme.json fails to load or is ignored, WordPress
produces no diagnostic output. In my environment WP_DEBUG, WP_DEBUG_LOG, and
WP_DEBUG_DISPLAY are all enabled and debug.log is wp-content/debug.log, yet
I see:

  • no entry in debug.log
  • no PHP notice or warning on screen
  • no Site Health warning
  • no message in the Site Editor's Fonts screen

The only evidence is a 404 in the web server access log and the browser falling
back to another font. This makes font problems in theme.json effectively
undebuggable.

I originally hit this while adding a Montserrat family to theme.json. Montserrat
was already installed in the Font Library with the same slug (montserrat), so the
theme's fontFace definitions were silently dropped. No warning was produced even
with WP_DEBUG enabled. I have also reproduced the same silence with a
fontFace.src pointing to a file that does not exist.

### Why it is silent

  1. WP_Font_Face_Resolver::to_theme_file_uri() (wp-includes/fonts/class-wp-font-face-resolver.php) converts file:./... to a theme URL via get_theme_file_uri(), but never checks file_exists(). A missing font file only becomes a browser 404.
  1. WP_Font_Face::validate_font_face_declarations() (wp-includes/fonts/class-wp-font-face.php) reports invalid faces with _doing_it_wrong(), which only emits a message when WP_DEBUG is true, then skips the face. There is no error_log() call and no admin notice.
  1. When a theme font family has the same slug as a Font Library family, the custom family wins during merge. The theme's fontFace array is dropped before it is validated or printed, and nothing is logged.
  1. WP_Theme_JSON_Resolver::read_json_file() (wp-includes/class-wp-theme-json-resolver.php) returns an empty array when decoding fails. wp_json_file_decode() reports the error through wp_trigger_error(), which returns early when WP_DEBUG is false. On a production site, an invalid theme.json is silently ignored.

### Steps to reproduce

Option A — missing file

  1. WordPress 7.1.3, block theme, WP_DEBUG=true, WP_DEBUG_LOG=true, WP_DEBUG_DISPLAY=true.
  2. Add this to theme.json:
{
  "settings": {
    "typography": {
      "fontFamilies": [
        {
          "fontFamily": "Montserrat, sans-serif",
          "name": "Montserrat",
          "slug": "montserrat-repro",
          "fontFace": [
            {
              "fontFamily": "Montserrat",
              "fontWeight": "400",
              "fontStyle": "normal",
              "src": ["file:./assets/fonts/missing.woff2"]
            }
          ]
        }
      ]
    }
  }
  1. Load the frontend.
  2. Check wp-content/debug.log and the page output.

Option B — slug shadowing

  1. Install Montserrat in the Font Library (slug montserrat).
  2. Add a montserrat font family with fontFace entries to theme.json.
  3. Load the Site Editor's Fonts screen and the frontend.
  4. Check wp-content/debug.log.

Expected
A diagnostic identifying the missing file or ignored family. At minimum, an entry
in debug.log when WP_DEBUG and WP_DEBUG_LOG are enabled, plus a Site Health or
Fonts screen notice when a theme font family is shadowed by a Font Library family.
Actual
No debug.log entry and no displayed error. The font silently falls back.
Suggested fix

  • Check file_exists() in to_theme_file_uri() (or before generating the

@font-face) and trigger a warning naming the missing file and family.

  • Replace the _doing_it_wrong() calls in WP_Font_Face with wp_trigger_error()

and add a core logger hooked to wp_trigger_error_always_run (WP 7.0+), or at
least use error_log() for invalid font faces.

  • Emit a warning when a theme font family is shadowed by a Font Library family with

the same slug.

  • Surface validation results in Site Health and the Fonts UI.

Environment

  • WordPress 7.1.3
  • PHP 8.4.x
  • Block theme Frost
  • MAMP / nginx, macOS
  • WP_DEBUG=true, WP_DEBUG_LOG=true, WP_DEBUG_DISPLAY=true
  • debug.log path: wp-content/debug.log

Change History (0)

Note: See TracTickets for help on using tickets.