---
url: "https://vueda.dev/v3/reference/api/py/vueda.core.exceptions.md"
title: "core.exceptions"
---

# core.exceptions

## Overview

Custom exception handler and validation error classes.

## Classes

- [BadRequestException](/v3/reference/api/py/vueda.core.exceptions/BadRequestException.md)
- [ConfirmationRequired](/v3/reference/api/py/vueda.core.exceptions/ConfirmationRequired.md)
- [VuedaValidationError](/v3/reference/api/py/vueda.core.exceptions/VuedaValidationError.md)

## `compute_warnings_digest` {#compute_warnings_digest}

Return a short, stable digest of a warnings mapping.

The digest is order-independent (keys are sorted) so that the same set of warnings always hashes
to the same value. The client echoes this digest back in the acknowledgement header; the gate is
only bypassed on an exact match, so a changed warning set produces a different digest and the
user is re-prompted instead of silently committing past warnings they never saw.

### Signature {#compute_warnings_digest-signature}

`compute_warnings_digest(warnings)`

#### Parameters {#compute_warnings_digest-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="compute_warnings_digest-param-warnings">warnings</span> |  | yes |  |  |

### Source {#compute_warnings_digest-source}

`server/vueda/core/exceptions.py:112`

## `debug_stack_exception_handler` {#debug_stack_exception_handler}

Custom exception handler which adds the exception class name to the response.

Every response built here is an error or a withheld write, so the request's atomic block is
marked for rollback first. DRF's own handler does this only for the exceptions it handles;
without it, ``ATOMIC_REQUESTS`` would commit writes made before an unhandled exception or a
``ConfirmationRequired``.

### Signature {#debug_stack_exception_handler-signature}

`debug_stack_exception_handler(exc, context)`

#### Parameters {#debug_stack_exception_handler-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="debug_stack_exception_handler-param-exc">exc</span> |  | yes |  |  |
| <span id="debug_stack_exception_handler-param-context">context</span> |  | yes |  |  |

### Source {#debug_stack_exception_handler-source}

`server/vueda/core/exceptions.py:48`

## `gate_warnings` {#gate_warnings}

Withhold a write behind an explicit confirmation when ``warnings`` is non-empty.

``warnings`` must be one of two shapes, chosen by the request path: the aggregate
``{field: [messages]}`` mapping for a single-object (detail) request, or no natural object to
attribute a warning to at all, or the per-object ``{object_id: {field: [messages]}}`` mapping,
one entry per warned object keyed by ``str(pk)``, for a bulk request. Use
``"non_field_errors"`` for a warning not tied to a field.

This gate only checks ``warnings`` for truthiness and digests it as opaque JSON — it does not
itself validate the shape — but a custom caller that returns the aggregate shape for a bulk
request breaks ``ModelActionForm``'s client-side object attribution: it groups a bulk action's
warnings into one display group per object id, and only falls back to a single unkeyed group
for a single-object action.

When ``warnings`` is falsy this returns immediately. Otherwise the digest from
``compute_warnings_digest`` is compared against the request's ``Acknowledge-Warnings`` header:
a match means the client has already shown these exact warnings to the user and they
confirmed, so the caller may proceed; anything else raises ``ConfirmationRequired`` (HTTP 409
with the warnings and digest), and the client re-submits with the digest once the user
confirms.

Call this from a custom action body after ``serializer.is_valid(raise_exception=True)`` (so
blocking validation errors surface as a 400 before the 409) and before any write or side
effect. ``WarningConfirmationMixin`` and the ``@action(confirm=True)`` mode route through this
same gate.

### Signature {#gate_warnings-signature}

`gate_warnings(request, warnings)`

#### Parameters {#gate_warnings-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="gate_warnings-param-request">request</span> |  | yes |  |  |
| <span id="gate_warnings-param-warnings">warnings</span> |  | yes |  |  |

### Source {#gate_warnings-source}

`server/vueda/core/exceptions.py:141`

## `page_not_found` {#page_not_found}

Return a JSON 404 response with ``{"detail": "Not found."}``. Set it as ``handler404`` in the root
URLconf.

### Signature {#page_not_found-signature}

`page_not_found(request, exception, args, kwargs)`

#### Parameters {#page_not_found-parameters}

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| <span id="page_not_found-param-request">request</span> |  | yes |  |  |
| <span id="page_not_found-param-exception">exception</span> |  | yes |  |  |
| <span id="page_not_found-param-args">args</span> |  | no |  |  |
| <span id="page_not_found-param-kwargs">kwargs</span> |  | no |  |  |

### Source {#page_not_found-source}

`server/vueda/core/exceptions.py:176`

## `ACKNOWLEDGE_WARNINGS_HEADER` {#ACKNOWLEDGE_WARNINGS_HEADER}

Request header carrying the warnings digest the client acknowledges.

## Source

`server/vueda/core/exceptions.py`
