Confluence has a nifty feature in that if you go to a page that does not exist, Confluence will check the database to see if there might be some obvious pages you might want to see instead, for example pages with the same name in a different space, pages that used to be called by that name but have since been renamed, or pages that start with the name you entered (in case the name was truncated when someone sent you the URL).
So we stay good Internet citizens, this page is still served with a 404 HTTP status code. This way robots, caches and the like know there isn’t _really_ a page at that URL.
This feature has been broken on Atlassian’s extranet for a while. If you go to a page that should return a redirect, you just get the generic error page instead. (CONF-8766)
I spent a long time trying to diagnose this. I couldn’t reproduce it locally. When I did the relevant query directly on the extranet database, it came back with the page I was looking for. When I downloaded the entire extranet database and tried it on my machine, I got the redirect page successfully.
Then I checked all the moving parts. There were only three differences between my environment and extranet: extranet is Linux and I’m on a Mac, extranet is clustered and I’m not, and extranet is running Tomcat 5.0 vs my Tomcat 5.5.
I prayed that it wasn’t a cluster bug.
Turns out it was the Servlet spec.
Confluence has a generic “404: not found” error page that it serves up when you try to go to some page that doesn’t exist. The Servlet Specification provides a reasonably simple mechanism for providing such a page, you just put a blob like this in

1
web.xml

, and the container will do the rest:


404</error-code>
/fourohfour.action</location>

In the Servlet 2.4 specification,

1
response.sendError()

and

1
response.setStatus()

are treated differently. The former redirects you to the configured error page, but the latter still assumes that you’re going to be providing the response yourself:
bq. If the

1
sendError

method is called on the response, the container consults the list of error page declarations for the Web application that use the

1
status-code

syntax and attempts a match. If there is a match, the container returns the resource as indicated by the location entry.
In the Servlet 2.3 specification, the two methods are treated the same. If you set the HTTP status response with either method and there’s a configured

1
 

for that status, the error page will be served in preference to whatever response you’ve come up with.
bq. If a status code indicating an error is set on the response, the container consults the list of error page declarations for the web application that use the

1
status-code

syntax and attempts a match. If there is a match, the container returns the resource as indicated by the location entry.
Given that most of our supported servers have long released 2.4-compliant versions, and rather than put in some kind of hacky fix that would have to be tested and maintained for the foreseeable future, I marked the bug Won’t Fix.