BIPIDA BLOG / WordPress migration

Why Images Disappear After a WordPress Migration

Fix broken images after a WordPress migration by checking the requested URL, HTTP status, file presence, permissions, mixed content, CDN state, attachment metadata, and thumbnails.

Published: Estimated reading time: 7 min

Images that disappear after a WordPress migration usually fall into one of four categories: the page requests the wrong URL, the file was not copied, the server cannot read or serve it, or WordPress references an image size that no longer exists. The visible broken-image icon does not identify which layer failed.

Quick answer: Inspect one failed image request in the browser Network panel and record its full URL and HTTP status. Compare that URL with the file expected under wp-content/uploads. If the URL contains the old domain, perform a reviewed serialization-safe replacement. If it returns 404, verify the copied path, filename case, thumbnail, rewrite, CDN, and origin. If it returns 403, inspect permissions and access rules. Fix the specific layer before regenerating thumbnails or replacing URLs globally.

Start with one exact failed request

Open developer tools, reload the affected page, and select a failed image. Record the request URL, status code, redirect chain, response headers, initiator, and whether the browser reports mixed content. Then open the URL directly and compare it with the HTML src and srcset.

This evidence separates database URL problems from filesystem and delivery problems. A Media Library thumbnail can fail for a different reason than the full-size file on a post.

Interpret the HTTP status before changing anything

  • 404: wrong URL, missing file, filename-case mismatch, missing thumbnail, origin path, or rewrite issue
  • 403: permission, ownership, hotlink protection, WAF, or storage policy
  • 301/302 loop: conflicting domain, HTTPS, CDN, or proxy rules
  • 5xx: origin, PHP image handler, proxy, storage, or resource failure
  • 200 with wrong content: soft error page, CDN response, or MIME/content corruption

Do not regenerate the entire library to solve an old-domain URL, and do not run search-and-replace to solve a missing file.

Check whether the requested file exists

Translate the URL path into the destination upload path and verify the exact filename. Linux filesystems are usually case-sensitive, so Photo.jpg and photo.jpg are different. Compare source and destination counts and sizes by year/month directories, and review transfer errors or exclusions.

Do not create empty placeholder files or copy only database attachment records. WordPress Media Library entries describe media, but the binary file must exist in storage.

Confirm the upload base URL and path

Standard installations generally serve media from wp-content/uploads, while plugins, multisite, offload tools, or historical settings may use another location. Inspect WordPress upload configuration and attachment metadata instead of assuming the path.

The official Media Library documentation distinguishes managed media records from the uploaded files they represent. A record visible in the library does not prove that the file is present on the new storage.

Find stale old-domain and old-path references

Inspect page HTML, post content, attachment URLs, CSS, widgets, page-builder data, theme options, and serialized plugin settings. If the domain or public path changed, use a serialization-aware replacement and start with a dry run:

wp search-replace 'https://old.example' 'https://new.example' --all-tables-with-prefix --dry-run

Review the affected scope before removing --dry-run. Search separately for HTTP, www, escaped URLs, CDN hosts, and previous staging domains. The new-domain migration guide covers safe URL replacement and redirect design.

Do not confuse a full-size image with its thumbnails

WordPress can generate several derived sizes when an image is uploaded. The original may exist while a specific -300x200 or theme-defined size is missing. Compare the failing filename with attachment metadata and the files on disk.

If a new theme or image-size configuration needs derivatives that were never generated, regenerate only after a backup and a sample test. Regeneration cannot recover a missing original.

Use thumbnail regeneration for the right problem

The official wp media regenerate command can rebuild attachment thumbnails and supports limiting work to missing files or selected sizes. Start with specific attachment IDs or a staging copy before processing a large library.

wp media regenerate 123 --skip-delete
wp media regenerate --only-missing --yes

The attachment ID is an example. Review plugin compatibility, available disk, CPU, memory, and backup state. Avoid deleting unknown sizes until you know that external pages or cached content no longer reference them.

Check ownership and permissions

The web server needs read access to served media and appropriate write access for new uploads and generated thumbnails. Correct ownership depends on the deployment model; there is no universal command. Compare a working file and directory with a failing one.

Do not use chmod 777. Broad write access hides the ownership problem and increases risk. WordPress documentation notes that media uploads depend on suitable permissions for wp-content.

Test a new upload on the destination

Upload a small non-sensitive image through Media Library. Confirm that WordPress creates the original and expected sizes, the browser can retrieve them, and the file owner matches the runtime design. Then remove the test item through WordPress if it is no longer needed.

If old media works but new uploads fail, focus on write permission, disk space, temporary directory, PHP upload limits, image libraries, and storage integration. If new media works but old media fails, focus on copy completeness, URL drift, and metadata.

Detect mixed content after HTTPS migration

An HTTPS page that requests an HTTP image may be blocked or downgraded by the browser. Inspect the console and final image URL. Fix the stored or generated source URL and ensure WordPress detects HTTPS correctly behind a proxy.

Do not solve mixed content by disabling browser protection. The official WordPress HTTPS guidance also highlights correct proxy headers to avoid redirect and scheme problems.

Separate CDN failure from origin failure

Request the image through the public CDN and, using an authorized method, directly from the origin with the correct Host header. Compare status, cache headers, content type, and body. A stale negative cache can continue serving a 404 after the file arrives.

Verify the CDN origin hostname, path prefix, TLS, access policy, cache key, image optimization, and purge scope. Purge a specific test URL before clearing the entire cache.

Review media-offload and object-storage configuration

Offload plugins may rewrite URLs and expect objects in S3-compatible storage or another provider. Confirm bucket, region, endpoint, credentials, object prefix, public/private policy, signed-URL behavior, and CORS. Never expose credentials while debugging.

A database copied without the corresponding object store—or objects copied without updated metadata—produces a partially working library.

Inspect srcset and responsive image candidates

The main src may work while the browser selects a broken candidate from srcset based on viewport or pixel density. Inspect the actual request, not only the HTML's first URL. Missing derivatives and stale CDN transformations often appear only on certain devices.

Test representative desktop and mobile widths and clear device-specific CDN variants after correcting the origin.

Check CSS backgrounds and lazy-loading layers

Some images come from inline styles, generated CSS, page-builder assets, JavaScript lazy loading, or optimization plugins rather than attachment HTML. Inspect the request initiator. Regenerate builder CSS only if its documented cache contains the stale path, and keep a rollback copy.

A blank placeholder can also mean JavaScript failed before replacing a lazy-load attribute. Check console errors and compare the rendered DOM.

Verify filename encoding and letter case

Migrations between filesystems may expose differences in Unicode normalization, letter case, spaces, or non-ASCII filenames. Compare the exact URL-encoded request with the stored filename. Do not bulk-rename media without updating every database and metadata reference.

For a small affected set, a controlled rename plus attachment-reference update may be safer than a global transformation.

Validate after the fix

  1. Retest the original failed image and its page.
  2. Check full-size and responsive variants.
  3. Test a new upload and thumbnail creation.
  4. Review browser console, application log, and CDN response.
  5. Crawl for image 404/403 responses and old-host references.
  6. Confirm disk usage and backup coverage.

Do not consider the repair complete because one browser shows a cached image. Test with cache bypass and from the public delivery path.

Common mistakes

  • Regenerating thumbnails before checking whether originals exist
  • Running raw SQL replacement on serialized data
  • Using 777 to mask ownership errors
  • Purging all CDN cache without testing the origin
  • Ignoring srcset, CSS backgrounds, and lazy loading
  • Assuming a Media Library record means the file was copied
  • Deleting old thumbnails before external references expire

When is specialist help appropriate?

If thousands of media files, object storage, a CDN transformer, serialized builder data, or mixed filesystem conventions are involved, bulk changes can expand the damage. The WordPress migration service can compare storage, URLs, metadata, and delivery before applying a scoped repair.

Frequently asked questions

Why are images visible in Media Library but not on pages?

The attachment record may exist while the requested file, derivative size, URL, permission, CDN object, or responsive candidate is wrong.

Will regenerating thumbnails restore missing originals?

No. It can create derived sizes only when the original attachment file is available and readable.

Should I replace every old-domain string?

No. Use a dry run and classify matches; some email addresses, logs, identifiers, and external references may intentionally retain the old domain.

Why do images work on desktop but fail on mobile?

The browser may select a different srcset candidate, CDN transformation, or lazy-load path at another viewport and pixel density.

YOUR NEXT STEP

Need help with this issue?

Share the symptoms and what you have already tried in a support request.

Open a support ticket