Skip to content

[BUG] Throwing HttpError in view decorators results in ServerError #1588

@makisukurisu

Description

@makisukurisu

Describe the bug
If you try to throw a HttpError exception in a decorator that will be used in view mode (for example - as a router decorator), then ninja will throw error 500. And in dev mode - show a traceback.

Versions (please complete the following information):

  • Python version: 3.14.0
  • Django version: 5.2.8
  • Django-Ninja version: 1.5.0b1
  • Pydantic version: 2.12.4

Warning

Using a beta release, precisely because it has view decorators, which I also use for logging purposes.

Sample code for reproducibility:

from functools import wraps

from django.http import HttpRequest
from ninja import NinjaAPI, Router
from ninja.errors import HttpError


def error_decorator(func) -> object:
    @wraps(func)
    def wrapper(
        request: HttpRequest,
        *args: object,
        **kwargs: object,
    ) -> object:
        raise HttpError(401, "Unauthorized chat")

    return wrapper


app = NinjaAPI()


@app.get(
    "/direct_error",
)
def test_endpoint(request: HttpRequest) -> str:  # noqa: ARG001
    raise HttpError(401, "Unauthorized chat")


@app.get(
    "/error_in_decorator",
)
@error_decorator
def test_endpoint_with_decorator(request: HttpRequest) -> str:
    return "This will never be returned"


extra_router = Router()

extra_router.add_decorator(
    error_decorator,
    mode="view",
)


@extra_router.get(
    "/error_in_extra_decorator",
)
def test_endpoint_with_extra_decorator(request: HttpRequest) -> str:
    return "This will never be returned"


app.add_router("/extra", extra_router)

First two endpoints will raise 401 as expected, and the last one - will raise error 500.

Example from a working app:
Image

Rationale behind raising a HttpError in view decorator:
This way you can implement a decorator for performing some check for a common parameter, for example.
Then in your endpoints you can simply specify the necessary parameters, and apply a decorator to a router.

Maybe it's a little silly, but it does the job I have for it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions