[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 14:48:12 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:  General       |    Version:  6.8.2
 Severity:  normal        |   Keywords:
  Focuses:                |
--------------------------+-----------------------------
 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>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list