The WordPress 7.1 Icon Registration API reads file_path lazily. Registration can return success while the file is absent, case-mismatched, unreadable, excluded from a production package, or resolved through a broken symlink. The failure appears later as empty icon content during REST retrieval or server rendering, often only on Linux production hosts.
Use this for plugins and themes that bundle SVG files and behave correctly on a case-insensitive local workstation but lose icons after Composer, npm, zip, rsync, container, symlink, or release-directory deployment.
Quick answer
Resolve the absolute path on the running release, verify the exact filename case, file type, permissions, package contents, and process-user readability, then call wp_get_icon() and the icon REST endpoint after a cold deployment. Record a checksum from source and production. Registration success is only the first assertion because file_path is opened when content is requested. Fail the deployment if any manifest icon is missing, empty, unreadable, or different from the reviewed asset.
What to check first
- Print the absolute file_path value produced by the deployed plugin or theme, without exposing private server roots publicly.
- Compare source and production filenames byte for byte, including case, extension, Unicode normalization, and directory separators.
- Inspect release archives, Composer or npm ignore files, container layers, symlink targets, ownership, mode, and process-user readability.
- Request every manifest icon through wp_get_icon() and the REST collection after clearing object and page caches.
- Store source and production checksums so a partial deploy or stale release mount is distinguishable from sanitization.
Why this usually happens
- A case-insensitive development filesystem hides a filename mismatch.
- The SVG directory is excluded from the production package or container layer.
- A release symlink changes while PHP workers retain paths or caches from the prior release.
- File permissions allow the deploy user to read an asset but deny the web process.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
# Run inside the deployed release
find wp-content/plugins/acme-icons -type f -name '*.svg' -print
sha256sum wp-content/plugins/acme-icons/public/icon/*.svg
wp eval "var_dump( wp_get_icon( 'acme-icons/alert' ) );"
wp cache flush
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence to collect | How to verify |
| Generate an icon manifest with exact relative paths and expected checksums. | Print the absolute file_path value produced by the deployed plugin or theme, without exposing private server roots publicly. | Production contains every reviewed SVG at the expected exact path. |
| Include the SVG directory in every build, archive, container, and deployment allowlist. | Compare source and production filenames byte for byte, including case, extension, Unicode normalization, and directory separators. | The web process can read each asset without broader permissions. |
| Resolve paths from the extension directory instead of the process working directory. | Inspect release archives, Composer or npm ignore files, container layers, symlink targets, ownership, mode, and process-user readability. | wp_get_icon() and REST return nonempty content after cold cache tests. |
| Run cold PHP and REST smoke tests as the production process user. | Request every manifest icon through wp_get_icon() and the REST collection after clearing object and page caches. | Rollback restores the prior icon manifest and rendered output. |
Decision rule
Promote the release only when every manifest path exists with exact case, is readable by the web process, matches its reviewed checksum, and returns nonempty sanitized content through PHP and REST.
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| Local macOS | Cake.svg requested as cake.svg | Fixture catches case mismatch |
| Linux release | Exact path and process user | Readable nonempty SVG |
| Symlink deploy | Current release changes | Path follows owned target |
| Cold REST | No object or page cache | Every manifest icon has content |
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Generate an icon manifest with exact relative paths and expected checksums.
- Include the SVG directory in every build, archive, container, and deployment allowlist.
- Resolve paths from the extension directory instead of the process working directory.
- Run cold PHP and REST smoke tests as the production process user.
- Block promotion when any registered icon returns empty content or a checksum mismatch.
Production verification checklist
- Production contains every reviewed SVG at the expected exact path.
- The web process can read each asset without broader permissions.
- wp_get_icon() and REST return nonempty content after cold cache tests.
- Rollback restores the prior icon manifest and rendered output.
What to tell the client or owner
Give the site owner the affected versions, exact synthetic fixture, UTC timeline, before and after evidence, cause class, decision, rollback point, unresolved risks, and next review date. State which measurements prove success and which observation window remains open.
Mistakes to avoid
- Changing production before recording exact versions, UTC timestamps, settings, stable fixture IDs, and a reproducible baseline.
- Treating one successful screen as proof that keyboard access, APIs, caches, jobs, reports, analytics, and downstream records agree.
- Testing only an administrator session instead of the devices, roles, networks, locales, and failure branches customers use.
- Closing the work without a named owner, rollback point, observation window, and contextual incoming link from an established guide.
Questions teams ask during testing
Can this be tested on production?
Use production for read-only checks and one narrow synthetic fixture that cannot charge a card, send customer email, expose personal data, or change inventory. Run upgrades, package changes, cache changes, and destructive repairs on staging first.
What evidence should the test report keep?
Keep exact versions, UTC timestamps, stable synthetic IDs, expected and actual results, screenshots or response excerpts, the decision owner, rollback point, and final verification. Redact credentials, tokens, customer data, private addresses, and infrastructure details.
How long should the observation window stay open?
Keep it open long enough to include at least one cache cycle, scheduled job cycle, and representative traffic period. For release changes, include logged-in and logged-out use plus the first real operational handoff.
When is the task complete?
Complete it when the primary user path passes, downstream records reconcile, failure branches are understood, monitoring is active, and an established owner page links to this guide in context.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, repair a WordPress deployment.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Helpful references