aosabook/500lines · error · ServerException
'{0}' not found
Error message
'{0}' not found What it means
Thrown by case_no_file.act in a teaching web server (the 500 Lines 'A Python Web Server' chapter). The request handler first translates the URL into handler.full_path; case_no_file.test returns True when os.path.exists(handler.full_path) is False, and act raises ServerException with the requested path. The handler's outer try/except catches ServerException and renders a 404 page, so this is the server's canonical 'file or directory does not exist' signal.
Source
Thrown at web-server/code/05-refactored/server.py:41
def index_path(self, handler):
return os.path.join(handler.full_path, 'index.html')
def test(self, handler):
assert False, 'Not implemented.'
def act(self, handler):
assert False, 'Not implemented.'
#-------------------------------------------------------------------------------
class case_no_file(base_case):
'''File or directory does not exist.'''
def test(self, handler):
return not os.path.exists(handler.full_path)
def act(self, handler):
raise ServerException("'{0}' not found".format(handler.path))
#-------------------------------------------------------------------------------
class case_cgi_file(base_case):
'''Something runnable.'''
def run_cgi(self, handler):
cmd = "python " + handler.full_path
child_stdin, child_stdout = os.popen2(cmd)
child_stdin.close()
data = child_stdout.read()
child_stdout.close()
handler.send_content(data)
def test(self, handler):
return os.path.isfile(handler.full_path) and \
handler.full_path.endswith('.py')
View on GitHub (pinned to fba689d101)
Solutions
- Verify the resource exists under the configured root: os.path.exists on the exact handler.full_path value.
- Check the URL->path translation (the root join) for off-by-one slashes or a missing Root dereference.
- Correct the URL casing/typo to match the on-disk filename.
- Restore or recreate the missing file/directory, or register it with the server.
- If the path legitimately may be absent, add a case before case_no_file to serve a configured fallback.
Example fix
// before: requesting a missing resource
GET /inde.html HTTP/1.1 -> raises ServerException("'/inde.html' not found")
// after: validate the path translation before the case loop
full_path = os.path.join(Root, handler.path.lstrip('/'))
if not os.path.exists(full_path):
# log the resolved path, fix Root or the URL, then retry Defensive patterns
Strategy: validation
Validate before calling
# before issuing/extending a case, confirm the path exists
import os
full_path = os.path.join(ROOT_DIR, path.lstrip('/'))
if not os.path.exists(full_path):
# log and return a 404 rather than letting ServerException propagate
return False Try / catch
# if you extend the handler, catch the server's own exception type
try:
handler.handle_request()
except ServerException as e:
log.warning('request failed: %s', e) Prevention
- Keep all servable resources under a single ROOT_DIR and serve paths relative to it.
- Add an integration test that requests every published URL and asserts 200.
- On case-sensitive filesystems, assert filenames match the URL exactly in CI.
- Log handler.full_path on failure so resolution bugs are obvious.
When it happens
Trigger: Any GET/HEAD request whose resolved filesystem path does not exist: a typo'd URL, a deleted file, a missing directory, or a path whose case does not match the on-disk filename. It fires only after os.path.exists(handler.full_path) returns False, i.e. before any file/directory/CGI case is evaluated.
Common situations: Wrong document root configured so full_path points outside the intended tree; URL->path join that mishandles a leading/trailing slash; files renamed or moved after deployment; case-sensitivity mismatch when deploying from macOS/Windows to Linux; a symlink whose target was removed.
AI-assisted analysis of aosabook/500lines@fba689d101 (2026-08-13).
Data as JSON: /api/errors/f9b81ae97b1362b1.
Report an issue: GitHub.