Make WordPress Core

Opened 4 months ago

Last modified 4 months ago

#63707 new defect (bug)

Grid mode in the Media Library breaks if video metadata contains invalid sizes dimensions

Reported by: magnifin's profile magnifin Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 6.8.2
Component: Media Keywords:
Focuses: Cc:

Description (last modified by sabernhardt)

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

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
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 запис(ів)");
        }
});

Attachments (2)

2025-07-15-[18-37-53].jpg (38.1 KB) - added by magnifin 4 months ago.
2025-07-15-[18-36-38].jpg (101.8 KB) - added by magnifin 4 months ago.

Download all attachments as: .zip

Change History (6)

#1 @magnifin
4 months ago

Additional error noticed in the logs when switching between Grid/List view:

PHP Warning:  Undefined array key "full" in /wp-includes/media.php on line 4666
PHP Warning:  Trying to access array offset on null in /wp-includes/media.php on line 4666

#2 @sabernhardt
4 months ago

  • Component changed from General to Media
  • Description modified (diff)

#3 follow-up: @thabotswana
4 months ago

Hi @magnifin,

Please check the report shared below.

Reproduction Report

I've tested this ticket, but was unable to reproduce the described issue. The Media Library grid mode worked as expected after switching between views.

Environment

  • OS: macOS 15.5
  • Web Server: Nginx
  • PHP: 8.3.23
  • WordPress: 6.8.2
  • Browser: Chrome 138.0.7204.158
  • Theme: Course

Actual Results

  • ❌ Unable to repro.

Supplemental Artifacts

You can view a screen recording here: https://d.pr/v/cHnYHQ

#4 in reply to: ↑ 3 @magnifin
4 months ago

Replying to thabotswana:

Thanks, I completely disabled all plugins on the staging server and activated the Twenty Twenty-Five theme
Web server: Nginx 1.28
PHP: 8.3.21
WordPress: 6.8.2
Browser: Chrome 138.0.7204.158
But the result is the same - it freezes. The only thing I noticed is that your switching between list and grid was a little slower, mine is faster. Number of posts 411237

Last edited 4 months ago by magnifin (previous) (diff)
Note: See TracTickets for help on using tickets.