International Customized Server Error Messages

Using XSSI and ErrorDocument to

configure customized international server error responses


This document describes an easy way to provide your apache

WWW server with a set of customized error messages which take

advantage of


to return error messages

generated by the server in the client’s native language.

By using XSSI, all

can share a homogenous and consistent style and layout, and

maintenance work (changing images, changing links) is kept to a

minimum because all layout information can be kept in a single


Error documents can be shared across different servers, or

even hosts, because all varying information is inserted at the

time the error document is returned on behalf of a failed


Content Negotiation then selects the appropriate language

version of a particular error message text, honoring the

language preferences passed in the client’s request. (Users

usually select their favorite languages in the preferences

options menu of today’s browsers). When an error document in

the client’s primary language version is unavailable, the

secondary languages are tried or a default (fallback) version

is used.

You have full flexibility in designing your error documents

to your personal taste (or your company’s conventions). For

demonstration purposes, we present a simple generic error

document scheme. For this hypothetic server, we assume that all

error messages…

An example of a “document not found” message for a german

client might look like this:

All links in the document as well as links to the server’s

administrator mail address, and even the name and port of the

serving virtual host are inserted in the error document at

“run-time”, i.e., when the error actually occurs.

For this concept to work as easily as possible, we must take

advantage of as much server support as we can get:

By defining the , we

enable the language selection of the most appropriate

language alternative (content negotiation).

By setting the

directive we define a set of default fallback languages in

the situation where the client’s browser did not express any

preference at all.

By enabling

(and disallowing execution of cgi scripts for

security reasons), we allow the server to include building

blocks of the error message, and to substitute the value of

certain environment variables into the generated document

(dynamic HTML) or even to conditionally include or omit parts

of the text.




are useful for automatically XSSI-expanding all files with a

.shtml suffix to text/html.

By using the

directive, we

keep the error document directory outside of the document

tree because it can be regarded more as a server part than

part of the document tree.

The -Block

restricts these “special” settings to the error document

directory and avoids an impact on any of the settings for the

regular document tree.

For each of the error codes to be handled (see RFC2068

for an exact description of each error code, or look at

src/main/http_protocol.c if you wish to see

apache’s standard messages), an


the aliased /errordocs directory is defined.

Note that we only define the basename of the document here

because the MultiViews option will select the best candidate

based on the language suffixes and the client’s preferences.

Any error situation with an error code not handled

by a custom document will be dealt with by the server in the

standard way (i.e., a plain error message in


Finally, the

directive tells apache that it is not necessary to look for a

.htaccess file in the /errordocs directory: a minor speed


The resulting httpd.conf configuration would then

look similar to this: (Note that you can define your own

error messages using this method for only part of the document

tree, e.g., a /~user/ subtree. In this case, the configuration

could as well be put into the .htaccess file at the root of the

subtree, and the and

directives -but not the contained directives- must be


LanguagePriority en fr de




AllowOverride none

Options MultiViews IncludesNoExec FollowSymLinks

AddType text/html .shtml

AddHandler server-parsed .shtml


“400 Bad Request”,





“401 Authorization Required”,





“403 Forbidden”,





“404 Not Found”,





“500 Internal Server Error”,




The directory for the error messages (here:

/usr/local/apache/errordocs/) must then be created

with the appropriate permissions (readable and executable by

the server uid or gid, only writable for the administrator).

By defining the MultiViews option, the server was

told to automatically scan the directory for matching variants

(looking at language and content type suffixes) when a

requested document was not found. In the configuration, we

defined the names for the error documents to be just their

error number (without any suffix).

The names of the individual error documents are now

determined like this (I’m using 403 as an example, think of it

as a placeholder for any of the configured error


By putting as much layout information in two special “include

files”, the error documents can be reduced to a bare minimum.

One of these layout files defines the HTML document header

and a configurable list of paths to the icons to be shown in

the resulting error document. These paths are exported as a set

of XSSI environment variables and are later evaluated by the

“footer” special file. The title of the current error (which is

put into the TITLE tag and an H1 header) is simply passed in

from the main error document in a variable called


By changing this file, the layout of all generated

error messages can be changed in a second. (By

exploiting the features of XSSI, you can easily define

different layouts based on the current virtual host, or even

based on the client’s domain name).

The second layout file describes the footer to be displayed

at the bottom of every error message. In this example, it shows

an apache logo, the current server time, the server version

string and adds a mail reference to the site’s webmaster.

For simplicity, the header file is simply called

head.shtml because it contains server-parsed

content but no language specific information. The footer file

exists once for each language translation, plus a symlink for

the default language.

Example: for English, French and German

versions (default english)


foot.shtml symlink to


Both files are included into the error document by using the



respectively: the rest of the magic occurs in mod_negotiation

and in mod_include.


to see an

actual HTML implementation of the discussed example.

After all this preparation work, little remains to be said

about the actual documents. They all share a simple common


explanatory error text

In the , you can see an

example of a [400 Bad Request] error document. Documents as

simple as that certainly cause no problems to translate or


Do we need a special handling for languages other than those we

have translations for? We did set the LanguagePriority, didn’t


Well, the LanguagePriority directive is for the case where

the client does not express any language priority at all. But

what happens in the situation where the client wants one of the

languages we do not have, and none of those we do have?

Without doing anything, the Apache server will usually

return a [406 no acceptable variant] error, listing the choices

from which the client may select. But we’re in an error message

already, and important error information might get lost when

the client had to choose a language representation first.

So, in this situation it appears to be easier to define a

fallback language (by copying or linking, e.g., the

english version to a language-less version). Because the

negotiation algorithm prefers “more specialized” variants over

“more generic” variants, these generic alternatives will only

be chosen when the normal negotiation did not succeed.

A simple shell script to do it (execute within the

errordocs/ dir):

for f in *.shtml.en


ln -s $f `basename $f .en`


As of Apache-1.3, it is possible to use the

ErrorDocument mechanism for proxy error messages

as well (previous versions always returned fixed predefined

error messages).

Most proxy errors return an error code of [500 Internal

Server Error]. To find out whether a particular error document

was invoked on behalf of a proxy error or because of some other

server error, and what the reason for the failure was, you can

check the contents of the new ERROR_NOTES CGI

environment variable: if invoked for a proxy error, this

variable will contain the actual proxy error message text in

HTML form.

The following excerpt demonstrates how to exploit the

ERROR_NOTES variable within an error document:

The server encountered an unexpected condition

which prevented it from fulfilling the request.

SUBJECT=”Error message [] for “>

Please forward this error screen to ‘s

WebMaster; it includes useful debugging information about

the Request which caused the error.

So, to summarize our example, here’s the complete listing of

the 400.shtml.en document. You will notice that it

contains almost nothing but the error text (with conditional

additions). Starting with this example, you will find it easy

to add more error documents, or to translate the error

documents to different languages.

Your browser sent a request that this server could not understand:

The request could not be understood by the server due to malformed

syntax. The client should not repeat the request without


Please inform the owner of

“>the referring page about

the malformed link.

Please check your request for typing errors and retry.

Here is the complete head.shtml file (the funny

line breaks avoid empty lines in the document after XSSI

processing). Note the configuration section at top. That’s

where you configure the images and logos as well as the apache

documentation directory. Look how this file displays two

different logos depending on the content of the virtual host

name ($SERVER_NAME), and that an animated apache logo is shown

if the browser appears to support it (the latter requires

server configuration lines of the form

BrowserMatch “^Mozilla/[2-4]” anigif

for browser types which support animated GIFs).

</p> <p>[<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --></p> <p>


If you have tips to contribute, send mail to

Leave a Reply

Your email address will not be published.