A soft 404 appears when Google receives a successful response but the rendered page looks missing, empty, or broken. The mismatch leaves visitors on an unusable page and tells crawlers that an error document is valid content.

At the server edge, Nginx can correct one retired URL without changing sibling paths. An exact-match location = /retired-product route keeps the existing custom error body available to visitors.

Use a 404 or 410 only when the URL has no close replacement. A permanently moved page needs a 301 redirect to its closest replacement, while a page that should still exist needs its intended main content restored with 200; Search Console reflects the repair after Google recrawls the URL.

Steps to fix a soft 404 for a removed URL in Nginx:

  1. Fetch the affected URL's response headers without following redirects.
    $ curl --head https://www.example.com/retired-product
    HTTP/1.1 200 OK
    Content-Type: text/html

    A 200 response is suspicious when the page says that content is missing, renders almost nothing, or shows an application error.

  2. Inspect the affected URL's response body for missing, blank, or broken main content.
    $ curl --silent https://www.example.com/retired-product
    <!doctype html><html><body><main><h1>Product not found</h1><p>This product is no longer available.</p></main></body></html>
  3. Classify the retired URL as removed only when it has no close replacement.
  4. Find the active Nginx server block for www.example.com. Illustrative output:
    $ sudo nginx -T
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    # configuration file /etc/nginx/nginx.conf:
    ##### snipped #####
    # configuration file /etc/nginx/sites-enabled/www.example.com.conf:
    server {
        listen 443 ssl;
        server_name www.example.com;
    ##### snipped #####
        location = /retired-product {
            default_type text/html;
            return 200 '<!doctype html><html><body><main><h1>Product not found</h1><p>This product is no longer available.</p></main></body></html>';
        }
    }
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  5. Resolve the active configuration path printed by nginx -T to its canonical source.
    $ sudo readlink -f /etc/nginx/sites-enabled/www.example.com.conf
    /etc/nginx/sites-available/www.example.com.conf

    The example active file is a symlink, so readlink prints its source under /etc/nginx/sites-available/; a regular active file resolves to its own path.

  6. Edit the canonical source path printed by readlink to replace the retired URL's exact-match location with a 404 response.
    $ sudoedit /etc/nginx/sites-available/www.example.com.conf
    location = /retired-product {
        default_type text/html;
        return 404 '<!doctype html><html><body><main><h1>Product not found</h1><p>This product is no longer available.</p></main></body></html>';
    }
  7. Test the Nginx configuration for syntax and referenced-file errors.
    $ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  8. Reload Nginx to apply the corrected exact-match route.
    $ sudo nginx -s reload
  9. Verify the repaired URL returns 404 on its first response.
    $ curl --head https://www.example.com/retired-product
    HTTP/1.1 404 Not Found
    Content-Type: text/html
Share this guide