fastapi-knowledge-patch
FastAPI Knowledge Patch (0.112 to 0.135.3)
Claude's baseline knowledge covers FastAPI through 0.111, Pydantic v2.7, Starlette 0.37, Uvicorn 0.29. This skill covers changes from 0.112 through 0.135.3 (2024-09 to 2026-04).
Version Compatibility
| Dependency | Minimum | Notes |
|---|---|---|
| Python | 3.10 | Dropped 3.8 in 0.125.0, 3.9 in 0.129.0. Python 3.14 supported |
| Pydantic | 2.9.0 | v1 fully dropped (0.126.0-0.128.0). No pydantic.v1 compat |
| Starlette | >=0.46.0 | Supports Starlette 1.0.0+ |
fastapi-slim |
-- | Dropped in 0.129.2. Use fastapi or fastapi[standard] |
Key Changes Timeline
| Version | Change | Impact |
|---|---|---|
| 0.135.0 | Native SSE via fastapi.sse |
New API |
| 0.134.0 | yield streaming (JSON lines, binary) |
New pattern |
| 0.133.0 | Starlette 1.0 support | on_event removed |
| 0.132.0 | strict_content_type=True default |
Breaking |
| 0.131.0 | ORJSONResponse/UJSONResponse deprecated | Deprecation |
| 0.130.0 | Pydantic Rust JSON serializer auto-used | Performance |
| 0.129.1 | bytes JSON Schema: contentMediaType |
Breaking |
| 0.126.0 | Pydantic v1 support fully dropped | Breaking |
| 0.122.0 | Security classes return 401, not 403 | Breaking |
| 0.121.0 | Dependency scope="request" |
New API |
| 0.117.0 | -> None return type for no-body responses |
New pattern |
Server-Sent Events (0.135.0)
Native SSE via fastapi.sse. No third-party packages needed:
from collections.abc import AsyncIterable
from fastapi import FastAPI
from fastapi.sse import EventSourceResponse, ServerSentEvent
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.get("/items/stream", response_class=EventSourceResponse)
async def stream_items() -> AsyncIterable[Item]:
for item in items:
yield item # auto-serialized as JSON in data: field
For SSE fields (event, id, retry, comment), yield ServerSentEvent objects:
yield ServerSentEvent(data=item, event="item_update", id=str(i), retry=5000)
yield ServerSentEvent(raw_data="[DONE]", event="done") # raw_data skips JSON encoding
yield ServerSentEvent(comment="keep-alive") # comment-only event
dataandraw_dataare mutually exclusive onServerSentEvent- Works with
def(sync) too -- useIterable[T]return type - Auto keep-alive ping every 15s,
Cache-Control: no-cache,X-Accel-Buffering: noset by default - Works with any HTTP method (not just GET) -- relevant for MCP-style POST SSE
See sse.md for Last-Event-ID resumption pattern and advanced usage.
strict_content_type (0.132.0) -- Breaking Change
FastAPI now checks Content-Type header on JSON requests by default. Requests without application/json are rejected with 422. Disable per-route:
@app.post("/legacy", strict_content_type=False)
async def legacy_endpoint(data: MyModel):
...
Dependency Scopes (0.121.0)
scope="request" makes yield dependency exit code run before the response is sent:
@app.get("/items/")
async def read_items(db: Annotated[Session, Depends(get_db, scope="request")]):
...
Without scope="request" (default), exit code runs after the response is fully sent -- correct for StreamingResponse where the dep must stay alive during streaming.
See dependency-injection.md for functools.partial() support and Response as dependency annotation.
Security Classes Return 401 (0.122.0) -- Breaking Change
HTTPBearer, OAuth2, HTTPBasic etc. now raise 401 (not 403) when credentials are missing. Tests asserting status_code == 403 will break.
ORJSONResponse / UJSONResponse Deprecated (0.131.0)
No longer needed. FastAPI 0.130.0+ uses Pydantic's Rust-based JSON serializer automatically when a Pydantic return type annotation or response_model is declared. Without either, falls back to jsonable_encoder.
Pydantic 2.12 Highlights
MISSING sentinel -- canonical solution for PATCH endpoints (distinguish "not provided" from None):
from pydantic.experimental.missing_sentinel import MISSING
class UpdateItem(BaseModel):
name: str | None | MISSING = MISSING
price: float | None | MISSING = MISSING
item = UpdateItem()
item.model_dump() # {} -- MISSING fields excluded
exclude_if -- conditional field exclusion:
value: int = Field(ge=0, exclude_if=lambda v: v == 0)
@model_validator(mode='after') must now be an instance method (not @classmethod). See pydantic-updates.md for all Pydantic 2.9-2.12 changes.
Starlette 1.0 Removals (0.133.0+)
Hard removals (not just deprecated -- will raise errors):
| Removed | Replacement |
|---|---|
@app.on_event("startup"/"shutdown") |
lifespan= context manager |
on_startup/on_shutdown params |
lifespan= context manager |
@app.route() |
routes= parameter |
@app.exception_handler() |
exception_handlers= parameter |
@app.middleware() |
middleware= parameter |
TemplateResponse(name, context) |
TemplateResponse(request, name, ...) |
Jinja2Templates: autoescape enabled by default. jinja2 must be installed to import.
Lifespan Migration Pattern
# BROKEN in Starlette 1.0:
@app.on_event("startup") # AttributeError -- hard removed
async def startup():
...
# CORRECT:
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
# startup
yield
# shutdown
app = FastAPI(lifespan=lifespan)
Typed Lifespan State (Starlette 0.52.0)
Access lifespan state with type safety via TypedDict:
from typing import AsyncIterator, TypedDict
from contextlib import asynccontextmanager
import httpx
class AppState(TypedDict):
http_client: httpx.AsyncClient
@asynccontextmanager
async def lifespan(app) -> AsyncIterator[AppState]:
async with httpx.AsyncClient() as client:
yield {"http_client": client}
# In route handler -- typed access:
async def handler(request: Request[AppState]):
client = request.state["http_client"] # typed as httpx.AsyncClient
See starlette-changes.md for CORSMiddleware, FileResponse range, ClientDisconnect.
None Return Type (0.117.0)
Valid return annotation for endpoints with no body (204, 304):
@app.delete("/items/{item_id}", status_code=204)
async def delete_item(item_id: int) -> None:
...
Streaming with yield (0.134.0)
Path operations can yield to stream responses directly -- no manual StreamingResponse needed. Requires Starlette >=0.46.0.
functools.partial() Dependencies (0.123.5)
Dependencies now fully support functools.partial() and functools.wraps():
from functools import partial
def get_db(engine: Engine, read_only: bool = False):
...
get_prod_db = partial(get_db, engine=prod_engine)
@app.get("/items")
async def read_items(db=Depends(get_prod_db)):
...
See dependency-injection.md for full details.
Reference Files
| File | Contents |
|---|---|
sse.md |
SSE Last-Event-ID resumption, advanced ServerSentEvent usage |
breaking-changes.md |
All breaking changes: strict_content_type, 401 security, bytes schema, Starlette 1.0 removals |
pydantic-updates.md |
Pydantic 2.9-2.12: MISSING sentinel, exclude_if, temporal config, model_validator changes |
dependency-injection.md |
Scopes, functools.partial/wraps, Response as dep, PEP 695 TypeAliasType |
starlette-changes.md |
Starlette 0.39-1.0: typed lifespan state, CORSMiddleware, FileResponse range, ClientDisconnect |
ecosystem.md |
SQLModel 0.0.25-0.0.36, Uvicorn changes, FastAPI Cloud CLI |
More from nevaberry/nevaberry-plugins
dioxus-knowledge-patch
Dioxus changes since training cutoff (latest: 0.7.4) — Signals replacing use_state, RSX macro overhaul, server functions, asset!() system, dx CLI, Element-as-Result. Load before working with Dioxus.
46rust-knowledge-patch
Rust changes since training cutoff (latest: 1.94.0) \u2014 Rust 2024 Edition, async closures, trait upcasting, new std APIs, cargo resolver v3. Load before working with Rust.
20postgresql-knowledge-patch
PostgreSQL changes since training cutoff (latest: 18.1) — JSON_TABLE, SQL/JSON functions, MERGE RETURNING, virtual generated columns, UUIDv7, temporal PRIMARY KEY. Load before working with PostgreSQL.
16bun-knowledge-patch
Bun changes since training cutoff (latest: 1.3.10) \u2014 S3 client, built-in SQL/Redis, route-based HTTP server, CSS bundler, V8 compatibility. Load before working with Bun.
14nextjs-knowledge-patch
Next.js changes since training cutoff (latest: 16.1) — proxy.ts, \"use cache\", Cache Components, navigation hooks, typed routes, auto PageProps, React 19.2. Load before working with Next.js.
14postgis-knowledge-patch
PostGIS changes since training cutoff (latest: 3.6.1) — SFCGAL CG_* rename, ST_CoverageClean, ST_AsRasterAgg, topology bigint IDs, viewport simplification, 3D SFCGAL ops. Load before working with PostGIS.
13