This is a very technical post. If you have no knowledge and no interest in code, skip it and read something else in the blog. Otherwise, let’s get to it.
Recently, one of my clients started having issues with some of the posts on her website. The website basically crashed when trying to load said posts, showing an error message on the front-end (something which I’d say is pretty rare in WordPress, as it usually goes just blank).
The message went like this (this is a shortened version):
Fatal error: Uncaught TypeError: Unsupported operand types: string * float in /wordpress-directory/wp-includes/media.php:467 Stack trace: #0 /wordpress-directory/wp-includes/media.php(717): wp_constrain_dimensions('150', '', 120) #1 /wordpress-directory/wp-includes/media.php(1379): wp_image_matches_ratio(120, 45, '150', '') #2 /wordpress-directory/wp-includes/media.php(1697): wp_calculate_image_srcset(Array, 'http://www.prof...', Array, 4021) #3 /wordpress-directory/wp-includes/media.php(2013): wp_image_add_srcset_and_sizes('apply_filters('', Array) #10 /wordpress-directory/wp-includes/post-template.php(429): apply_filters('get_the_excerpt', '', Object(WP_Post)) #11 /wordpress-directory/wp-content/plugins/wordpress-seo/src/helpers/post-helper.php(72): get_the_excerpt(Object(WP_Post))
This shows that there is an issue with the type cast. PHP is not the most robust language when it comes to typing: variables were not initially typed, and it was only later that it added typing. In order to make the language backwards-compatible, typing isn’t always enforced. As a result, sometimes things can get messy, just like in this case.
As indicated by the crash, the issue is in the file media.php, line 467, and is caused by the fact that WordPress expects an int but received a String instead. If we look at lines 467 and 468, they are the following:
$w = max( 1, (int) round( $current_width * $ratio ) ); $h = max( 1, (int) round( $current_height * $ratio ) );
The Quick and Dirty Fix
The quick and dirty fix to this problem is to just copy the two lines that cause the crash, and edit them, adding the following highlighted code:
$w = max( 1, (int) round( (int)$current_width * $ratio ) ); $h = max( 1, (int) round( (int)$current_height * $ratio ) );
(int) forces a cast from String to int of the value stored in $current_width and $current_height.
The original two lines can be commented.
NOTE that this is a TEMPORARY fix. media.php is a core WordPress file, which will be overwritten when WordPress updates. This is just a workaround to minimize the posts’ downtime and to not have to solve it in a hurry.
The Source of the Problem
But what is the origin of the problem? In my client’s case, it was an issue caused by some images’ metadata. The metadata was found in the wp_postmeta table (remember to replace wp_ with your table’s prefix).
In particular, the issue was with meta_key =’_wp_attachment_metadata’ and the corresponding meta_value included this bit:
As you can see, there is a width value of “150” between quotes, making it a String. This is also enforced by the s:3 preceding the “150”. The s:3 indicates that the next value is a String and has 3 characters. This happens again for the height, although in this case, the value is a String of 0 characters (s:0:””).
The quickest way to solve this is by editing the data directly.
The Real Fix
Please note!! Directly editing the database can break the website. You should never do it unless you know what you’re doing. Even if you do, create a backup before making any changes, to ensure that you’ll be able to revert to the previous database’s state if needed.
To properly fix it, the meta_value needs to be edited, and replace s:3:”150” by i:150. The same can be done for the height, in this case replacing s:0:”” by i:0. The i indicates that it is an int.
After the changes, the data should look like this:
To date, I haven’t yet figured out what caused the problem in the first place, as a few months earlier the image metadata didn’t include the “corrupt” data. My guess is that it has something to do with Elementor; maybe there was an issue with some update to the database data.