An image file on disk is not enough. WordPress stores an attachment record, relative upload path and metadata for generated sizes; the web server must then map the requested URL to a readable file. Migrations often break one of those links.
Start with one image and trace URL, database metadata and filesystem path before regenerating the whole library.
Capture the failing request
Inspect the broken <img src> or CSS URL and request it directly. Record status, redirects, content type, response body and cache/CDN headers.
Interpret:
404 -> path/routing/file-name mismatch
403 -> permissions/hotlink/security
500 -> rewrite/PHP/CDN transform
200 HTML -> wrong route/cache/login page
SSL/mixed content -> scheme/domain
Do not publish private attachment URLs.
Map URL to filesystem
Confirm WordPress upload base URL/directory and the expected year/month/file.ext path. Inspect the attachment’s _wp_attached_file through WordPress APIs.
$relative = get_post_meta( $attachment_id, '_wp_attached_file', true );
Log the relative path only for a controlled public image. Avoid editing serialized attachment metadata directly.
Check case sensitivity: Image.jpg and image.jpg may work on one host but differ on Linux.
Verify original and derivatives
The original may exist while a requested thumbnail size is missing. Inspect _wp_attachment_metadata and compare generated filenames/dimensions.
Do not rename files manually without updating metadata. Use WordPress media regeneration tools on a staging copy and a bounded production batch.
Preserve originals and check free disk/inodes before creating many derivatives.
Check migrated URLs
Search for old domain, HTTP scheme or staging path in post content, builders, featured images and CSS. Use a serialisation-aware dry-run replacement.
wp search-replace 'https://old.example' 'https://example.com' --all-tables-with-prefix --dry-run
Review matches and do not replace GUIDs or signed external URLs blindly.
Inspect permissions and ownership
The web server needs read/traverse access to uploads and parent directories. Compare a working image’s owner/mode with the failing file.
Use cPanel/Plesk/host ownership repair. Do not apply recursive 777 or make private uploads public.
Check ACLs, hotlink protection and security rules when the server returns 403.
Review rewrite and offload/CDN configuration
Image optimisation/offload plugins may rewrite local URLs to a CDN or object store. Confirm the object exists, is accessible under intended policy and cache key matches case/path.
If local files are fallback, test with rewriting disabled in staging. Do not purge/delete remote originals before validating the complete library.
Check Nginx/Apache rules do not route real media through WordPress incorrectly.
Handle filenames and encoding
Accented/space/unicode filenames can change encoding during transfer. Compare exact bytes/names on source and destination.
Prefer a controlled WordPress-aware rename/migration that updates attachment metadata and references. Do not mass-normalise names without redirect/mapping; indexed URLs and content may break.
Test English, Spanish and Catalan media examples.
Handle files copied without attachment records
A filesystem-only migration can copy images while omitting their WordPress attachment posts/metadata. The files may work at direct URLs but not appear in Media Library or generate responsive sizes.
Use a trusted media-import tool on staging to create records for an explicit bounded file list. Do not bulk-register cache thumbnails or plugin-generated files as originals. Preserve dates/paths where required and check for duplicates by checksum, not filename alone.
Inspect responsive and lazy-loading markup
The main src may exist while one candidate in srcset is missing, so the image breaks only on particular screens. Inspect which candidate the browser selects.
Check lazy-load attributes and placeholder replacement scripts. A JavaScript failure can leave placeholders even when URLs work. Repair attachment sizes/markup first; do not disable responsive images globally to hide one missing derivative.
Verify media integrity
Test original, thumbnails, responsive srcset, editor insertion, featured image and CDN after cache warm-up. Run a bounded broken-link/media audit.
Recurring care should include uploads in migration/restore tests and monitor image 4xx. The repair is complete when database, disk and public URL agree for existing and newly uploaded files.