Skip to main content

Internal Framework Errors and Deprecations

FastAPI maintains internal integrity and guides developers through framework evolution using a set of specialized exceptions and warnings. Unlike standard Python exceptions, these are designed to catch specific architectural mismatches or provide visible feedback on deprecated features that might otherwise go unnoticed.

Framework Deprecation Strategy

FastAPI uses a custom FastAPIDeprecationWarning (defined in fastapi/exceptions.py) to signal features that are slated for removal. This class inherits from UserWarning rather than the standard DeprecationWarning.

The Choice of UserWarning

The decision to use UserWarning is a deliberate design choice to ensure visibility. In many Python environments (including the default Python interpreter), DeprecationWarning is ignored by default. By using a UserWarning subclass, FastAPI ensures that developers see these warnings in their console during development without requiring special flag configurations.

This warning is frequently encountered when using legacy response classes or parameters that have been superseded by newer Pydantic v2 patterns. For example, in fastapi/responses.py, both ORJSONResponse and UJSONResponse trigger this warning upon instantiation:

class ORJSONResponse(JSONResponse):
def __init__(
self,
content: Any,
status_code: int = 200,
headers: Mapping[str, str] | None = None,
media_type: str | None = None,
background: BackgroundTask | None = None,
) -> None:
warnings.warn(
"ORJSONResponse is deprecated, use fastapi.responses.JSONResponse instead",
category=FastAPIDeprecationWarning,
stacklevel=2,
)
super().__init__(content, status_code, headers, media_type, background)

Similarly, in fastapi/params.py, using the regex parameter in Query or Path (which has been replaced by pattern) or the example parameter (replaced by examples) will trigger a FastAPIDeprecationWarning.

Pydantic Version Enforcement

With the transition to Pydantic v2, FastAPI introduced the PydanticV1NotSupportedError. This exception is a subclass of FastAPIError and represents a hard constraint: FastAPI no longer supports Pydantic v1 models in its core data processing pipelines.

Enforcement Points

The framework checks for Pydantic v1 models at two critical stages:

  1. Route Analysis: In fastapi/utils.py, the create_model_field function checks if an annotation is a Pydantic v1 model. If a developer attempts to use a pydantic.v1.BaseModel as a response model or request body, FastAPI raises this error during the application startup phase.
  2. Serialization: In fastapi/encoders.py, the jsonable_encoder utility performs a runtime check. If it encounters an instance of a Pydantic v1 model, it raises the error to prevent incorrect serialization.
# From fastapi/encoders.py
if is_pydantic_v1_model_instance(obj):
raise PydanticV1NotSupportedError(
"pydantic.v1 models are no longer supported by FastAPI."
f" Please update the model {obj!r}."
)

This design forces a clean migration to Pydantic v2, avoiding the complexity and potential bugs of maintaining a dual-version compatibility layer for data validation and serialization.

Dependency Lifetime Integrity

The DependencyScopeError is used to enforce logical consistency in the dependency injection system. It specifically addresses the relationship between dependency lifetimes (scopes).

Scope Mismatch Logic

In FastAPI, dependencies can have different scopes (e.g., "request" or "function"). A critical rule implemented in fastapi/dependencies/utils.py is that a dependency with a broader scope cannot depend on one with a narrower scope.

The framework specifically monitors generator dependencies (which use yield). If a generator dependency is determined to have a "request" scope, it is prohibited from depending on a dependency with a "function" scope.

# Logic in fastapi/dependencies/utils.py
if (
(dependant.is_gen_callable or dependant.is_async_gen_callable)
and dependant.computed_scope == "request"
and param_details.depends.scope == "function"
):
raise DependencyScopeError(
f'The dependency "{call_name}" has a scope of '
'"request", it cannot depend on dependencies with scope "function".'
)

Reasoning and Tradeoffs

This restriction exists because a "request" scoped dependency is intended to live for the duration of the entire HTTP request. If it were allowed to depend on a "function" scoped dependency, the lifecycle of the sub-dependency would be ambiguous or prematurely terminated, leading to "leaked" resources or closed generators when the parent dependency still expects them to be active.

By raising DependencyScopeError during the dependency tree resolution (usually at startup), FastAPI prevents subtle runtime bugs related to resource management and execution order in complex dependency graphs.