Handling Errors

starlette-context provides several error types that help identify and handle issues in your application.

ContextDoesNotExistError

This is the most common error you’ll encounter, raised when you try to access the context object outside of a request-response cycle.

Common Causes

1. Context Not Created

The most basic cause is trying to use the context object without adding one of the context middlewares to your application.

# This will fail with ContextDoesNotExistError
from starlette_context import context
value = context["key"]  # Error!

Make sure you’ve added either ContextMiddleware or RawContextMiddleware to your application:

from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette_context.middleware import ContextMiddleware

app = Starlette(middleware=[Middleware(ContextMiddleware)])

2. Incorrect Middleware Order

The order of middlewares matters. The context is only available after the context middleware has processed the request and before it processes the response:

class FirstMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        # Can't access context here!
        return await call_next(request)

class SecondMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        # Context is available here
        response = await call_next(request)
        # Context is still available here
        return response

middlewares = [
    Middleware(ContextMiddleware),  # Creates context
    Middleware(FirstMiddleware),    # Can't use context (runs before ContextMiddleware)
    Middleware(SecondMiddleware),   # Can use context (runs after ContextMiddleware)
]

For more details on middleware execution order, see Starlette issue #479.

3. Outside Request-Response Cycle

The context is only available during the request-response cycle. It doesn’t persist after the response is sent:

@app.route("/")
async def handler(request):
    context["value"] = "test"
    return JSONResponse({"message": "OK"})

# After the response is sent:
# context["value"]  # Would raise ContextDoesNotExistError

This applies to:

  • Logging outside of request handlers

  • Testing code that checks context after a request completes

Note on Background Tasks: Context may be available in background tasks due to Python’s ContextVar inheritance (PEP 567), but this is not guaranteed across all middleware types and Starlette versions. With RawContextMiddleware, background tasks run inside the middleware’s context manager, so context is reliably available. With ContextMiddleware (which uses BaseHTTPMiddleware), background tasks may run after the context has been reset, and availability depends on ContextVar inheritance to spawned tasks. To be safe, explicitly copy context data and pass it to background tasks. See the FastAPI Integration section for the recommended pattern.

Safe Access

Use context.exists() to check if the context is available before accessing it:

def log_with_context(message):
    if context.exists():
        logger.info(f"{message}", extra=context.data)
    else:
        logger.info(f"{message}")

For testing, either:

  • Return context data in the response: return JSONResponse(context.data)

  • Use the request_cycle_context context manager in tests:

from starlette_context import request_cycle_context, context

def test_with_context():
    with request_cycle_context({"initial": "value"}):
        context["test"] = "value"
        assert context["test"] == "value"

MiddleWareValidationError

This error is raised when a plugin encounters invalid data and needs to return an error response. It’s typically used within plugin implementations:

from starlette.responses import JSONResponse
from starlette_context.errors import MiddleWareValidationError

async def process_request(self, request):
    auth_header = request.headers.get("Authorization")
    if not auth_header:
        error_response = JSONResponse(
            {"error": "Missing authorization header"},
            status_code=401
        )
        raise MiddleWareValidationError(
            "Missing auth header",
            error_response=error_response
        )
    return auth_header

When this error is raised in a plugin, the middleware will catch it and return the provided error response.

ConfigurationError

This error is raised when there’s an issue with the configuration of the middleware or plugins:

from starlette_context.errors import ConfigurationError

# Raised when a plugin instance is invalid
if not isinstance(plugin, Plugin):
    raise ConfigurationError(f"Plugin {plugin} is not a valid instance")

This is typically an issue you’ll encounter during development when setting up the middleware incorrectly.