aosabook/500lines · error · ServerException

Unknown object '{0}'

Error message

Unknown object '{0}'

What it means

Thrown by case_always_fail.act, the terminal handler in the case dispatch chain. case_always_fail.test unconditionally returns True, so its act runs only when every earlier case (case_no_file, case_cgi_file, case_existing_file, and the directory cases) failed to match. It signals that the path exists but is none of the supported object types, raising ServerException("Unknown object '{path}'").

Source

Thrown at web-server/code/05-refactored/server.py:128

            handler.handle_error(msg)

    def test(self, handler):
        return os.path.isdir(handler.full_path) and \
               not os.path.isfile(self.index_path(handler))

    def act(self, handler):
        self.list_dir(handler, handler.full_path)

#-------------------------------------------------------------------------------

class case_always_fail(base_case):
    '''Base case if nothing else worked.'''

    def test(self, handler):
        return True

    def act(self, handler):
        raise ServerException("Unknown object '{0}'".format(handler.path))

#-------------------------------------------------------------------------------

class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    '''
    If the requested path maps to a file, that file is served.
    If anything goes wrong, an error page is constructed.
    '''

    Cases = [case_no_file(),
             case_cgi_file(),
             case_existing_file(),
             case_directory_index_file(),
             case_directory_no_index_file(),
             case_always_fail()]

    # How to display an error.
    Error_Page = """\

View on GitHub (pinned to fba689d101)

Solutions

  1. Inspect the object type of handler.full_path with os.path.isfile / os.path.isdir / os.path.islink to see which case should have matched.
  2. Ensure the Cases list includes handlers for every object type you serve (directory index, directory listing, CGI).
  3. Add a dedicated case before case_always_fail for the unhandled object type.
  4. If the object should not be served, treat this as expected behaviour and let the error page render.

Example fix

# before: Cases missing a directory-index case, so a real dir hits always_fail
Cases = [case_no_file(), case_cgi_file(), case_existing_file(), case_always_fail()]

# after: insert the directory cases before the catch-all
Cases = [case_no_file(),
         case_cgi_file(),
         case_existing_file(),
         case_directory_index_file(),
         case_directory_no_index_file(),
         case_always_fail()]
Defensive patterns

Strategy: validation

Validate before calling

# classify the object before relying on the case chain
import os
p = handler.full_path
kind = ('dir' if os.path.isdir(p) else
        'file' if os.path.isfile(p) else
        'special')
if kind == 'special':
    # add a case or reject explicitly before case_always_fail
    return None

Try / catch

try:
    for case in Cases:
        if case.test(handler):
            case.act(handler)
            break
except ServerException:
    # render the generic error page
    handler.error_page()

Prevention

When it happens

Trigger: handler.full_path exists but is not a regular file, not a CGI script, and not a servable directory (e.g. no index file and directory listing disabled/failed). Concretely: a socket, FIFO, device node, or a directory whose index case was omitted from the Cases list.

Common situations: A new filesystem object type was added but no case class was registered for it; the Cases list was reordered so a directory case is missing; requesting a special file like /dev/null through the server; permission issues that make stat behave oddly.


AI-assisted analysis of aosabook/500lines@fba689d101 (2026-08-13). Data as JSON: /api/errors/ca3266343f741d9d. Report an issue: GitHub.