[wp-trac] [WordPress Trac] #63707: Grid mode in the Media Library breaks if video metadata contains invalid sizes dimensions

WordPress Trac noreply at wordpress.org
Wed Jul 16 16:10:38 UTC 2025


#63707: Grid mode in the Media Library breaks if video metadata contains invalid
sizes dimensions
--------------------------+------------------------------
 Reporter:  magnifin      |       Owner:  (none)
     Type:  defect (bug)  |      Status:  new
 Priority:  normal        |   Milestone:  Awaiting Review
Component:  Media         |     Version:  6.8.2
 Severity:  normal        |  Resolution:
 Keywords:                |     Focuses:
--------------------------+------------------------------
Changes (by sabernhardt):

 * component:  General => Media


Old description:

> Summary:
>
> When uploading a video file (e.g. .mp4) to the Media Library, WordPress
> may store invalid image size data in the _wp_attachment_metadata field —
> for example:
>

> {{{
> 'sizes' => [ '60x60' => false ]
> }}}
>

> After switching between List and Grid view modes, especially back to
> Grid, the Media Library tries to access this data as if it were valid,
> resulting in:
>
> a JS freeze, empty display (no media shown)
>
> Steps to reproduce:
>
>     Upload a .mp4 file via Media Library (in Grid mode).
>
>     Switch to List view.
>
>     Make sure the uploaded video is visible.
>
>     Switch back to Grid mode.
>
> Now WordPress will save _wp_attachment_metadata
> {{{
> ['sizes'] = [ '60x60' => false ]
> }}}
>

> {{{
> s:5:"sizes";a:0:{}
> }}}
>
> .
>
> The Grid mode may hang, freeze, or fail to load media.
>
> Technical notes:
>
> This metadata is likely generated by wp_generate_attachment_metadata() or
> related logic, which assumes image processing.
>
> The frontend JS does not expect false values in sizes, which causes
> unexpected behavior.
>
> I'm reporting this as a WordPress user (not a developer). Please let me
> know if more context is needed.
>
> 🛠️ Temporary workaround:
>
> A filter can be used to prevent Grid mode from breaking when bogus sizes
> exist for video attachments:
>
> {{{#!php
> <?php
>
> add_filter('wp_prepare_attachment_for_js', function($response,
> $attachment) {
>         if ($response['type'] === 'video' && isset($response['sizes'])) {
>                 $only_bogus = true;
>                 foreach ($response['sizes'] as $key => $val) {
>                         if (!empty($val) && is_array($val) &&
> isset($val['width'])) {
>                                 $only_bogus = false;
>                                 break;
>                         }
>                 }
>                 if ($only_bogus) {
>                         unset($response['sizes']);
>                 }
>         }
>         return $response;
> }, 10, 2);
> }}}
>

> Additionally, I created a simple admin tool (plugin) to preview and
> optionally fix video metadata records with only invalid sizes:
> 1. To preview video attachments with invalid `sizes`, visit:
>    /wp-admin/?preview_video_sizes=1
> 2. To clean up the detected invalid `sizes`, visit:
>    /wp-admin/?fix_video_sizes=1
>

> {{{#!php
> <?php
> add_action('admin_init', function () {
>         if (!current_user_can('manage_options')) return;
>
>         require_once ABSPATH . 'wp-admin/includes/file.php';
>
>         $mode_preview = isset($_GET['preview_video_sizes']);
>         $mode_fix     = isset($_GET['fix_video_sizes']);
>
>         if (!$mode_preview && !$mode_fix) return;
>
>         global $wpdb;
>
>         $attachments = $wpdb->get_results("
>                 SELECT pm.post_id, pm.meta_value
>                 FROM {$wpdb->postmeta} pm
>                 JOIN {$wpdb->posts} p ON pm.post_id = p.ID
>                 WHERE pm.meta_key = '_wp_attachment_metadata'
>                   AND p.post_type = 'attachment'
>                   AND p.post_mime_type LIKE 'video/%'
>         ", ARRAY_A);
>
>         $matched = [];
>
>         foreach ($attachments as $row) {
>                 $meta = maybe_unserialize($row['meta_value']);
>                 if (!is_array($meta)) continue;
>
>                 if (!isset($meta['sizes']) || !is_array($meta['sizes']))
> continue;
>
>                 $sizes = $meta['sizes'];
>
>                 // умова: всі значення false або порожній масив
>                 $all_false = empty($sizes) || !array_filter($sizes,
> function ($v) {
>                         return $v !== false;
>                 });
>
>                 if ($all_false) {
>                         $matched[] = [
>                                 'id' => $row['post_id'],
>                                 'meta' => $meta
>                         ];
>                 }
>         }
>
>         if ($mode_preview) {
>                 echo "<h2>🔍 Аналіз відео-вкладень з проблемним
> 'sizes'</h2><ul>";
>                 foreach ($matched as $item) {
>                         $edit_link = admin_url('post.php?post=' .
> $item['id'] . '&action=edit');
>                         echo "<li><strong>ID:</strong> {$item['id']} — <a
> href='$edit_link' target='_blank'>📝 Редагувати</a><pre>";
>                         print_r($item['meta']['sizes']);
>                         echo "</pre></li><hr>";
>                 }
>                 echo "</ul><p><strong>Знайдено: " . count($matched) . "
> запис(ів)</strong></p>";
>                 exit;
>         }
>
>         if ($mode_fix) {
>                 $cleaned = 0;
>
>                 foreach ($matched as $item) {
>                         unset($item['meta']['sizes']);
>                         wp_update_attachment_metadata($item['id'],
> $item['meta']);
>                         error_log("✅ Cleaned attachment
> #{$item['id']}");
>                         $cleaned++;
>                 }
>
>                 exit("✅ Очищено: $cleaned запис(ів)");
>         }
> });
> }}}

New description:

 ==== Summary:

 When uploading a video file (e.g. .mp4) to the Media Library, WordPress
 may store invalid image size data in the `_wp_attachment_metadata` field —
 for example:


 {{{
 'sizes' => [ '60x60' => false ]
 }}}


 After switching between List and Grid view modes, especially back to Grid,
 the Media Library tries to access this data as if it were valid, resulting
 in:

 a JS freeze, empty display (no media shown)

 ==== Steps to reproduce:

 - Upload a .mp4 file via Media Library (in Grid mode).
 - Switch to List view.
 - Make sure the uploaded video is visible.
 - Switch back to Grid mode.

 Now WordPress will save `_wp_attachment_metadata`
 {{{
 ['sizes'] = [ '60x60' => false ]
 }}}


 {{{
 s:5:"sizes";a:0:{}
 }}}

 .

 The Grid mode may hang, freeze, or fail to load media.

 ==== Technical notes:

 This metadata is likely generated by `wp_generate_attachment_metadata()`
 or related logic, which assumes image processing.

 The frontend JS does not expect false values in sizes, which causes
 unexpected behavior.

 I'm reporting this as a WordPress user (not a developer). Please let me
 know if more context is needed.

 ==== 🛠️ Temporary workaround:

 A filter can be used to prevent Grid mode from breaking when bogus sizes
 exist for video attachments:

 {{{#!php
 <?php

 add_filter('wp_prepare_attachment_for_js', function($response,
 $attachment) {
         if ($response['type'] === 'video' && isset($response['sizes'])) {
                 $only_bogus = true;
                 foreach ($response['sizes'] as $key => $val) {
                         if (!empty($val) && is_array($val) &&
 isset($val['width'])) {
                                 $only_bogus = false;
                                 break;
                         }
                 }
                 if ($only_bogus) {
                         unset($response['sizes']);
                 }
         }
         return $response;
 }, 10, 2);
 }}}


 Additionally, I created a simple admin tool (plugin) to preview and
 optionally fix video metadata records with only invalid sizes:
 1. To preview video attachments with invalid `sizes`, visit:
    `/wp-admin/?preview_video_sizes=1`
 2. To clean up the detected invalid `sizes`, visit:
    `/wp-admin/?fix_video_sizes=1`


 {{{#!php
 <?php
 add_action('admin_init', function () {
         if (!current_user_can('manage_options')) return;

         require_once ABSPATH . 'wp-admin/includes/file.php';

         $mode_preview = isset($_GET['preview_video_sizes']);
         $mode_fix     = isset($_GET['fix_video_sizes']);

         if (!$mode_preview && !$mode_fix) return;

         global $wpdb;

         $attachments = $wpdb->get_results("
                 SELECT pm.post_id, pm.meta_value
                 FROM {$wpdb->postmeta} pm
                 JOIN {$wpdb->posts} p ON pm.post_id = p.ID
                 WHERE pm.meta_key = '_wp_attachment_metadata'
                   AND p.post_type = 'attachment'
                   AND p.post_mime_type LIKE 'video/%'
         ", ARRAY_A);

         $matched = [];

         foreach ($attachments as $row) {
                 $meta = maybe_unserialize($row['meta_value']);
                 if (!is_array($meta)) continue;

                 if (!isset($meta['sizes']) || !is_array($meta['sizes']))
 continue;

                 $sizes = $meta['sizes'];

                 // умова: всі значення false або порожній масив
                 $all_false = empty($sizes) || !array_filter($sizes,
 function ($v) {
                         return $v !== false;
                 });

                 if ($all_false) {
                         $matched[] = [
                                 'id' => $row['post_id'],
                                 'meta' => $meta
                         ];
                 }
         }

         if ($mode_preview) {
                 echo "<h2>🔍 Аналіз відео-вкладень з проблемним
 'sizes'</h2><ul>";
                 foreach ($matched as $item) {
                         $edit_link = admin_url('post.php?post=' .
 $item['id'] . '&action=edit');
                         echo "<li><strong>ID:</strong> {$item['id']} — <a
 href='$edit_link' target='_blank'>📝 Редагувати</a><pre>";
                         print_r($item['meta']['sizes']);
                         echo "</pre></li><hr>";
                 }
                 echo "</ul><p><strong>Знайдено: " . count($matched) . "
 запис(ів)</strong></p>";
                 exit;
         }

         if ($mode_fix) {
                 $cleaned = 0;

                 foreach ($matched as $item) {
                         unset($item['meta']['sizes']);
                         wp_update_attachment_metadata($item['id'],
 $item['meta']);
                         error_log("✅ Cleaned attachment #{$item['id']}");
                         $cleaned++;
                 }

                 exit("✅ Очищено: $cleaned запис(ів)");
         }
 });
 }}}

--

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/63707#comment:2>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list