If you’re running a local WordPress site or recently migrated data and started seeing strange behavior in the Media Library—like missing images, broken grid views, or a flood of PHP warnings—you’re not alone.
Many developers encounter issues where attachments exist in the database but are missing essential properties like post_status, post_mime_type, or even a valid ID. These “ghost attachments” can wreak havoc on both the Grid View (which relies on AJAX and JSON) and the List View (which displays PHP warnings).
Common Symptoms of Broken Media Entries
Grid view shows no images (just a loading spinner or blank thumbnails)
List view shows dozens of errors like:
Warning: Attempt to read property “ID” on null…
Notice: Function map_meta_cap was called incorrectly…
debug.log shows warnings from class-wp-media-list-table.php, post.php, or template.php
These issues are typically caused by incomplete attachment posts left behind from failed imports, plugin removals, database syncs, or corrupted uploads.
The Fix: Clean Up Invalid Attachments in Your Database
Here’s a simple code snippet you can drop into your functions.php to automatically detect and delete invalid media attachments.
PHP Cleanup Script:
add_action(‘init’, function () {
if (!is_admin()) return;
global $wpdb;
$attachments = $wpdb->get_results(”
SELECT ID FROM {$wpdb->posts}
WHERE post_type = ‘attachment’
“);
$deleted = 0;
foreach ($attachments as $attachment) {
$post = get_post($attachment->ID);
if (
empty($post) ||
empty($post->ID) ||
empty($post->post_status) ||
empty($post->post_mime_type)
) {
wp_delete_post($attachment->ID, true);
$deleted++;
}
}
echo “✅ Deleted $deleted invalid attachment(s). Please remove this cleanup code now.”;
exit;
});
Warning: It will break you site temporary but just remove the functions after you run it and you should be fine. The media libraries should be back on track.
What This Script Does
- Queries all media entries from wp_posts where post_type = ‘attachment’
- Loops through each attachment and verifies if:
- The post exists and is valid
- It has a valid ID, post_status, and post_mime_type
- If any field is missing, it deletes the attachment permanently (wp_delete_post() with true)
- Outputs how many broken entries were removed