Prevent fatal error in webp_uploads_filter_wp_get_attachment_image() when wp_get_attachment_image_src() returns false and during rest_prepare_attachment filtering#2565
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Unlinked AccountsThe following contributors have not linked their GitHub and WordPress.org accounts: @vladte4, @1aTa, @Dave-LB. Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases. If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
webp_uploads_filter_wp_get_attachment_image()webp_uploads_filter_wp_get_attachment_image() when wp_get_attachment_image_src() returns false
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## trunk #2565 +/- ##
==========================================
- Coverage 70.38% 70.35% -0.03%
==========================================
Files 91 91
Lines 7850 7867 +17
==========================================
+ Hits 5525 5535 +10
- Misses 2325 2332 +7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
mukeshpanchal27
left a comment
There was a problem hiding this comment.
Thanks @westonruter for the PR!
Here's what I tested:
-
Check out the
trunkbranch. -
Add the following filter to prevent the fatal error in
webp_uploads_filter_wp_get_attachment_image():add_filter( 'wp_get_attachment_image_src', '__return_false' );
-
Add new page and add Image block.
-
Check out the PR branch
fix/2563-fatal-error-in-get-attachment-image. -
Reload the page.
-
Select the same image that was uploaded in the previous test (in my case,
car.jpeg). -
Observe the critical error returned by the REST endpoint.
{
"code": "internal_server_error",
"message": "<p>There has been a critical error on this website.<\/p><p><a href=\"https:\/\/wordpress.org\/documentation\/article\/faq-troubleshooting\/\">Learn more about troubleshooting WordPress.<\/a><\/p>",
"data": {
"status": 500,
"error": {
"type": 1,
"message": "Uncaught TypeError: str_replace(): Argument #3 ($subject) must be of type array|string, null given in \/var\/www\/html\/wp-content\/plugins\/webp-uploads\/rest-api.php:41\nStack trace:\n#0 \/var\/www\/html\/wp-content\/plugins\/webp-uploads\/rest-api.php(41): str_replace('', 'car-300x169.avi...', NULL)\n#1 \/var\/www\/html\/wp-includes\/class-wp-hook.php(343): webp_uploads_update_rest_attachment(Object(WP_REST_Response), Object(WP_Post))\n#2 \/var\/www\/html\/wp-includes\/plugin.php(205): WP_Hook->apply_filters(Object(WP_REST_Response), Array)\n#3 \/var\/www\/html\/wp-includes\/rest-api\/endpoints\/class-wp-rest-attachments-controller.php(1081): apply_filters('rest_prepare_at...', Object(WP_REST_Response), Object(WP_Post), Object(WP_REST_Request))\n#4 \/var\/www\/html\/wp-includes\/rest-api\/endpoints\/class-wp-rest-posts-controller.php(669): WP_REST_Attachments_Controller->prepare_item_for_response(Object(WP_Post), Object(WP_REST_Request))\n#5 \/var\/www\/html\/wp-includes\/rest-api\/class-wp-rest-server.php(1287): WP_REST_Posts_Controller->get_item(Object(WP_REST_Request))\n#6 \/var\/www\/html\/wp-includes\/rest-api\/class-wp-rest-server.php(1120): WP_REST_Server->respond_to_request(Object(WP_REST_Request), '\/wp\/v2\/media\/(?...', Array, NULL)\n#7 \/var\/www\/html\/wp-includes\/rest-api\/class-wp-rest-server.php(435): WP_REST_Server->dispatch(Object(WP_REST_Request))\n#8 \/var\/www\/html\/wp-includes\/rest-api.php(471): WP_REST_Server->serve_request('\/wp\/v2\/media\/95')\n#9 \/var\/www\/html\/wp-includes\/class-wp-hook.php(341): rest_api_loaded(Object(WP))\n#10 \/var\/www\/html\/wp-includes\/class-wp-hook.php(365): WP_Hook->apply_filters('', Array)\n#11 \/var\/www\/html\/wp-includes\/plugin.php(570): WP_Hook->do_action(Array)\n#12 \/var\/www\/html\/wp-includes\/class-wp.php(418): do_action_ref_array('parse_request', Array)\n#13 \/var\/www\/html\/wp-includes\/class-wp.php(821): WP->parse_request('')\n#14 \/var\/www\/html\/wp-includes\/functions.php(1343): WP->main('')\n#15 \/var\/www\/html\/wp-blog-header.php(16): wp()\n#16 \/var\/www\/html\/index.php(17): require('\/var\/www\/html\/w...')\n#17 {main}\n thrown",
"file": "\/var\/www\/html\/wp-content\/plugins\/webp-uploads\/rest-api.php",
"line": 41
}
},
"additional_errors": []
}
| * @return string The filtered HTML. | ||
| */ | ||
| function webp_uploads_filter_wp_get_attachment_image( string $html, int $attachment_id, $size, bool $icon, array $attr ): string { | ||
| function webp_uploads_filter_wp_get_attachment_image( string $html, int $attachment_id, $size, bool $icon, $attr ): string { |
There was a problem hiding this comment.
Make $attachment_id accept string as well, and cast it to int afterward, as many plugins send the attachment ID as a string. This was also reported on the support forum:
https://wordpress.org/support/topic/fatal-error-after-2-7-0/
Co-authored-by: b1ink0 <b1ink0@git.wordpress.org>
|
@mukeshpanchal27 I'm having trouble reproducing the issue with the steps you reported. |
|
I think I can reproduce it now. I had to switch to WebP instead of AVIF, because I wasn't getting modern images generated at all 😕 And here: Both seem to be addressed by making sure that |
Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org>
|
@mukeshpanchal27 Please try now. |
|
Build for testing: |
Add `@covers` tags to the existing Test_WebP_Uploads_REST_API tests and add regression tests for the defensive guards in webp_uploads_update_rest_attachment(), covering a missing/non-string `source_url`, a missing/invalid mime source `file` in both the per-size and full-size loops, and non-array response data. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ssing non-string as arg
…filter Convert the query-string test into a data-provider-driven test covering an empty string, a query string, an array, and an invalid `false` value passed as the `$attr` argument, asserting each is normalized before being passed to the inner `webp_uploads_filter_wp_get_attachment_image` filter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reported issue has been addressed
| * @param string|mixed $html HTML img element or empty string on failure. | ||
| * @param int|numeric-string $attachment_id Image attachment ID. | ||
| * @param string|array{int, int} $size Requested image size. | ||
| * @param bool|mixed $icon Whether the image should fall back to a mime type icon. |
There was a problem hiding this comment.
This isn't actually ever not a bool as far as I know, but I figured best to just let this be untyped for consistency with the other params. Using mixed here prevents PHPCS from complaining that there is no native type hint.
There was a problem hiding this comment.
Pull request overview
This PR addresses a fatal type error in the WebP Uploads plugin’s wp_get_attachment_image filter callback when WordPress passes a non-array $attr value (notably when wp_get_attachment_image_src() returns false). It also hardens the REST API response mutation to avoid notices/fatals when expected array keys/types are missing.
Changes:
- Relax and normalize arguments in
webp_uploads_filter_wp_get_attachment_image()to safely handle non-string HTML, non-int attachment IDs, and string/non-array$attr. - Add defensive checks in
webp_uploads_update_rest_attachment()before rewritingsource_urlfields. - Add/extend PHPUnit coverage for these edge cases (including “no image returned” and REST API malformed data scenarios).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| plugins/webp-uploads/tests/test-rest-api.php | Adds tests covering REST response edge cases (missing/invalid source_url, invalid sources entries, non-array response data). |
| plugins/webp-uploads/tests/test-load.php | Adds tests for wp_get_attachment_image() rewrite behavior when wp_get_attachment_image_src() returns false and for $attr normalization. |
| plugins/webp-uploads/rest-api.php | Adds type/key guards to prevent invalid REST attachment data from triggering errors during source URL rewriting. |
| plugins/webp-uploads/hooks.php | Makes the wp_get_attachment_image filter callback resilient to core passing non-array $attr and other unexpected argument types. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
adamsilverstein
left a comment
There was a problem hiding this comment.
Thanks for the quick fix.
webp_uploads_filter_wp_get_attachment_image() when wp_get_attachment_image_src() returns falsewebp_uploads_filter_wp_get_attachment_image() when wp_get_attachment_image_src() returns false and harden rest_prepare_attachment filtering
webp_uploads_filter_wp_get_attachment_image() when wp_get_attachment_image_src() returns false and harden rest_prepare_attachment filteringwebp_uploads_filter_wp_get_attachment_image() when wp_get_attachment_image_src() returns false and during rest_prepare_attachment filtering
Summary
Fixes #2563
Relevant technical choices
See #2563 (comment)
Use of AI Tools
Claude Code with Claude Opus 4.8 used for code review and writing tests.