Skip to content

Exceptions

All waygate exceptions are defined in waygate.core.exceptions. The engine raises them from engine.check(), and WaygateMiddleware catches them to produce the appropriate HTTP response.

from waygate import (
    WaygateException,
    MaintenanceException,
    RouteDisabledException,
    EnvGatedException,
)

You usually don't import these directly

In a standard FastAPI setup, WaygateMiddleware handles all exceptions automatically. You only need to import them if you are building a custom adapter, custom response factory, or writing tests that inspect the raised exception.


Exception hierarchy

WaygateException
├── MaintenanceException
├── RouteDisabledException
└── EnvGatedException

WaygateException

Base class for all waygate exceptions. Catch this if you want a single handler for any waygate-raised error.

from waygate import WaygateException

MaintenanceException

Raised by engine.check() when a route (or the entire system via global maintenance) is in maintenance mode.

from waygate import MaintenanceException

Attributes

Attribute Type Description
reason str Human-readable maintenance reason, passed from the decorator or engine call
retry_after datetime \| None End of the maintenance window. The middleware writes this to the Retry-After response header so clients know when to retry. None if no window was scheduled.

In a custom response factory

accessing exception attributes
from starlette.requests import Request
from starlette.responses import HTMLResponse
from waygate import MaintenanceException

def maintenance_page(request: Request, exc: MaintenanceException) -> HTMLResponse:
    retry_msg = ""
    if exc.retry_after:
        retry_msg = f"<p>Back at {exc.retry_after.strftime('%H:%M UTC')}</p>"

    return HTMLResponse(
        f"<h1>Under Maintenance</h1><p>{exc.reason}</p>{retry_msg}",
        status_code=503,
    )

RouteDisabledException

Raised by engine.check() when a route has been permanently disabled.

from waygate import RouteDisabledException

Attributes

Attribute Type Description
reason str The reason the route was disabled

EnvGatedException

Raised by engine.check() when a route is restricted to specific environments and the current environment is not in the allowed list.

from waygate import EnvGatedException

Attributes

Attribute Type Description
path str The route key
current_env str The active environment name (the value WaygateEngine was constructed with)
allowed_envs list[str] The environments where the route is accessible

WaygateMiddleware returns 403 with JSON

When WaygateMiddleware catches an EnvGatedException, it returns a 403 with a structured JSON body containing code: "ENV_GATED", current_env, allowed_envs, and path.


Using exceptions in custom adapters

If you are building an adapter for a framework other than FastAPI, catch these exceptions in your middleware or request handler and map them to the appropriate HTTP responses.

Custom adapter middleware pattern
from waygate import (
    MaintenanceException,
    RouteDisabledException,
    EnvGatedException,
)

try:
    await engine.check(path, method)

except MaintenanceException as exc:
    # 503 with Retry-After header
    headers = {}
    if exc.retry_after:
        headers["Retry-After"] = exc.retry_after.isoformat()
    return Response(503, body={"error": exc.reason}, headers=headers)

except RouteDisabledException as exc:
    # 503, no Retry-After
    return Response(503, body={"error": exc.reason})

except EnvGatedException as exc:
    # 403 with JSON body
    return Response(403, body={
        "error": {
            "code": "ENV_GATED",
            "message": "This endpoint is not available in the current environment",
            "current_env": exc.current_env,
            "allowed_envs": exc.allowed_envs,
            "path": exc.path,
        }
    })

See Building your own adapter for a complete working example.