Redirect resolving to a 4xx error page
What is this issue?
This check reports a URL that redirects and whose redirect lands on a page that returns a 4xx status -- most often a 404.
The distinction from a plain broken page matters. Nobody chose for a page to disappear, but somebody did write this redirect, pointing it at an address that is now gone. The repair is in the redirect rule, not in the page that was requested.
For a URL to pass this check:
- If it redirects, the address it resolves to returns a working status.
Example: /old-product 301-redirects to /products/discontinued-item,
which returns 404. The redirect is doing its job and delivering visitors to an
error page.
5xx destinations are deliberately not reported here. A server error is a condition of the moment rather than a statement about where the redirect points.
Why it matters
A redirect into a 4xx is worse than either of its parts:
- Nothing is preserved. A redirect exists to carry the value of the old address to a new one. Pointing it at a 404 discards every link and every ranking signal the original URL had earned.
- It looks fine from the outside. The redirect returns 301, so link checkers that stop at the first hop report success. Only following the chain reveals it.
- Visitors are sent to the error on purpose. Somebody clicking an old link is deliberately routed to a page that does not exist.
- Crawl waste. Each attempt costs two requests and yields nothing.
It is graded important rather than critical, and only because of what sits beside it: a page whose redirect resolves to a 4xx also returns that 4xx, so "Broken internal links and pages" is raised against the same URL and already deducts a critical's worth for the content being unreachable. Grading this critical as well would charge one dead destination twice.
How to fix it
Repoint the redirect at a page that exists. The best target is the closest equivalent content -- the replacement product, the new category, the updated article.
If there is no equivalent, redirect to the parent. A category or section page is a far better destination than a 404, provided it is genuinely related. Do not redirect everything to the homepage; Google treats a homepage redirect for unrelated content as a soft 404 anyway.
If the content is genuinely gone, remove the redirect. A clean 404 (or
- at the original address is more honest than a redirect to one. Let the original URL answer for itself.
Follow the whole chain when you check. A redirect that passes a first-hop link check can still end in an error two hops later.
Audit redirect rules after a migration. These are almost always created by a bulk redirect map written against a URL list that has since changed.
Fix the links as well. Anything still linking to the original address is why the redirect is being exercised at all.
Examples
Example 1: A redirect that resolves
Scenario: A renamed article.
Passes because: the chain ends on a page that returns 200.
GET /blog/old-title -> 301 -> /blog/new-title
GET /blog/new-title -> 200Example 2: A redirect into a 404
Scenario: A migration redirect map written before the destination slugs were finalised.
Fails because: the chain resolves to an address that no longer exists.
GET /shop/old-sku-1182 -> 301 -> /products/discontinued-item
GET /products/discontinued-item -> 404Corrected version: repoint the rule at the replacement product, or at the category if there is no replacement.
GET /shop/old-sku-1182 -> 301 -> /products/replacement-sku-4410
GET /products/replacement-sku-4410 -> 200Example 3: A chain that only breaks at the end
Scenario: Two redirect rules layered by successive migrations.
Fails because: the first hop looks healthy to any checker that stops there.
GET /old/page -> 301 -> /new/page
GET /new/page -> 301 -> /newest/page
GET /newest/page -> 410Corrected version: collapse the chain to a single hop pointing at live content, and remove the intermediate rule.
How PixyScan detects this
Records the redirect chain. As each page is fetched, PixyScan keeps every hop the request travelled through, in order, with the status each one returned.
Notes where the chain resolved. The final address and the status it returned are recorded alongside the chain.
Reports when the chain ended in the 400-499 range. A chain that resolves to 200 is fine. One that resolves to a 5xx is not reported here -- a server error is a transient condition, not a statement about the redirect target.
Requires a redirect to have happened. An address that simply returns 404 without redirecting is a broken page, which is a separate check with a separate fix.
Reports the whole chain, so the hop that needs repointing is visible on the row rather than needing to be reproduced by hand.
What we store
Storage Level
Page Level
Database Table / Prisma Model
audit_issues.details
Stored Fields
| Field | Type | Description |
|---|---|---|
| originalUrl | String | The address that was requested |
| finalUrl | String | Where the redirect chain resolved to |
| finalStatusCode | Int | The status that address returned |
| chain | String[] | Every hop, in the order it was travelled |
Detection Dependencies
- HTTP Response
- Redirect Chain
Note
The chain itself is also stored on the RedirectChain row for this scan, with
a status code per hop. The finding keeps its own copy of the URLs so the issue
row reads on its own.