flask_more_smorest.error.exceptions

Exception classes for Flask-More-Smorest API errors.

This module provides a hierarchy of exception classes for handling API errors, with RFC 7807 Problem Details format, automatic logging, and debug information.

The error responses follow RFC 7807 (Problem Details for HTTP APIs): https://datatracker.ietf.org/doc/html/rfc7807

Example response:
{

“type”: “https://api.example.com/errors/not_found_error”, “title”: “Not Found”, “status”: 404, “detail”: “User with id 123 doesn’t exist”, “instance”: “/api/users/123”

}

Exceptions

ApiException([message])

Base exception class for all API errors.

BadRequestError([message])

400 Bad Request error.

ConflictError([message])

409 Conflict error.

DBError([message])

Database error (500 status code).

DomainNotFoundError([message])

Requested domain was not found.

ForbiddenError([message, operation, ...])

403 Forbidden error with permission context.

InternalServerError([message])

500 Internal Server Error.

NoDomainAccessError([message, operation, ...])

User does not have access to the requested domain.

NotFoundError([message])

404 Not Found error.

UnauthorizedError([message])

401 Unauthorized error.

UnprocessableEntity(fields[, location, ...])

422 Unprocessable Entity error for validation failures.

exception flask_more_smorest.error.exceptions.ApiException(message=None, **kwargs)[source]

Base exception class for all API errors.

This exception class provides automatic error response generation following RFC 7807 Problem Details format, along with logging and debug information collection.

TITLE

Human-readable error title (default: “Error”)

MESSAGE_PREFIX

Prefix for error messages (default: “”)

HTTP_STATUS_CODE

HTTP status code for the error (default: 500)

INCLUDE_TRACEBACK

Whether to include traceback in response. Set to None to use environment-aware default (enabled in debug/testing). Set to True/False to override explicitly.

debug_context

Additional context information for debugging

Example

>>> class MyCustomError(ApiException):
...     TITLE = "Custom Error"
...     HTTP_STATUS_CODE = HTTPStatus.BAD_REQUEST
>>> raise MyCustomError("Something went wrong")
TITLE = 'Error'
MESSAGE_PREFIX = ''
HTTP_STATUS_CODE = 500
INCLUDE_TRACEBACK: bool | None = None
__init__(message=None, **kwargs)[source]

Initialize the API exception.

Parameters:
  • message (str | None) – Error message to display

  • **kwargs (str | int | bool | None) – Additional context information

custom_args: dict[str, str | int | bool | None]
property debug_context: dict[str, str | int | bool | dict | None]

Lazily compute debug context on first access.

This property defers the expensive operation of collecting user context until the debug context is actually needed (typically only in debug mode when generating error responses).

Returns:

Dictionary containing debug context including user information

classmethod error_code()[source]

Get the error code for this exception type.

Return type:

str

Returns:

Snake-case error code derived from class name

get_debug_context(**kwargs)[source]

Get debugging context information.

Collects user context via the configurable user context system, which works with both built-in and custom User models.

Parameters:

**kwargs (str | int | bool | None) – Additional context information to include

Return type:

dict[str, str | int | bool | dict | None]

Returns:

Dictionary containing debug context including user information (in debug mode)

make_error_response()[source]

Create an RFC 7807 Problem Details response.

Returns a response following the RFC 7807 format: - type: URI identifying the error type - title: Human-readable title - status: HTTP status code - detail: Human-readable explanation - instance: URI of the resource (if in request context)

In debug/testing mode, additional fields are included: - debug: Object containing traceback and context

Return type:

Response

Returns:

Flask Response object with problem details

log_exception()[source]

Log the exception with the appropriate level based on severity.

Return type:

None

exception flask_more_smorest.error.exceptions.NotFoundError(message=None, **kwargs)[source]

404 Not Found error.

TITLE = 'Not Found'
HTTP_STATUS_CODE = 404
exception flask_more_smorest.error.exceptions.ForbiddenError(message=None, *, operation=None, resource_type=None, resource_id=None, reason=None, **kwargs)[source]

403 Forbidden error with permission context.

Provides detailed information about permission failures including the operation attempted, resource type, resource ID, and failure reason.

operation

Operation attempted (e.g., ‘modify’, ‘create’, ‘delete’)

resource_type

Type of resource (e.g., ‘Article’, ‘User’)

resource_id

ID of the specific resource

reason

Human-readable reason for denial

TITLE = 'Forbidden'
HTTP_STATUS_CODE = 403
__init__(message=None, *, operation=None, resource_type=None, resource_id=None, reason=None, **kwargs)[source]

Initialize ForbiddenError with permission context.

Parameters:
  • message (str | None) – Error message (auto-generated if not provided)

  • operation (str | None) – Operation attempted (e.g., ‘modify’, ‘create’, ‘delete’)

  • resource_type (str | None) – Type of resource (e.g., ‘Article’, ‘User’)

  • resource_id (Any) – ID of the specific resource

  • reason (str | None) – Human-readable reason for denial

  • **kwargs (str | int | bool | None) – Additional debug_context information

exception flask_more_smorest.error.exceptions.UnauthorizedError(message=None, **kwargs)[source]

401 Unauthorized error.

TITLE = 'Unauthorized'
INCLUDE_TRACEBACK: bool | None = False
HTTP_STATUS_CODE = 401
exception flask_more_smorest.error.exceptions.BadRequestError(message=None, **kwargs)[source]

400 Bad Request error.

TITLE = 'Bad Request'
HTTP_STATUS_CODE = 400
exception flask_more_smorest.error.exceptions.ConflictError(message=None, **kwargs)[source]

409 Conflict error.

TITLE = 'Conflict'
HTTP_STATUS_CODE = 409
exception flask_more_smorest.error.exceptions.UnprocessableEntity(fields, location='json', message=None, valid_data=None, **kwargs)[source]

422 Unprocessable Entity error for validation failures.

This exception follows RFC 7807 with additional validation-specific fields: - errors: Object mapping locations to field errors

fields

Dictionary of field names to error messages

location

Where the validation failed (json, query, file, etc.)

valid_data

Data that passed validation (if any)

TITLE = 'Validation Error'
HTTP_STATUS_CODE = 422
__init__(fields, location='json', message=None, valid_data=None, **kwargs)[source]

Initialize the UnprocessableEntity exception.

Parameters:
  • fields (dict[str, str]) – Dictionary mapping field names to error messages

  • location (str) – Where the error occurred (default: “json”)

  • message (str | None) – Overall error message (default: “Invalid input data”)

  • valid_data (dict[str, str | int | bool] | None) – Data that passed validation

  • **kwargs (str | int | bool | None) – Additional debug_context information

fields: dict[str, str]
location: str | None
valid_data: dict[str, str | int | bool] | None
make_error_response()[source]

Create an RFC 7807 response with validation errors.

Extends the base Problem Details format with validation-specific fields: - errors: Object mapping location to field-level errors

Return type:

Response

Returns:

Flask Response object with validation error details

exception flask_more_smorest.error.exceptions.InternalServerError(message=None, **kwargs)[source]

500 Internal Server Error.

TITLE = 'Internal Server Error'
HTTP_STATUS_CODE = 500
get_debug_context(**kwargs)[source]

Get debugging context including exception information.

Parameters:

**kwargs (str | int | bool | None) – Additional context information

Return type:

dict[str, str | int | bool | dict | None]

Returns:

Dictionary with base context plus exception details

exception flask_more_smorest.error.exceptions.DBError(message=None, **kwargs)[source]

Database error (500 status code).

TITLE = 'Database Error'
HTTP_STATUS_CODE = 500
exception flask_more_smorest.error.exceptions.NoDomainAccessError(message=None, *, operation=None, resource_type=None, resource_id=None, reason=None, **kwargs)[source]

User does not have access to the requested domain.

TITLE = 'Domain Access Denied'
MESSAGE_PREFIX = 'User does not have access to this domain.'
exception flask_more_smorest.error.exceptions.DomainNotFoundError(message=None, **kwargs)[source]

Requested domain was not found.

TITLE = 'Domain Not Found'
MESSAGE_PREFIX = 'Domain not found.'