The Fix
Upgrade to version 0.49.3 or later.
Based on closed Kludex/starlette issue #2912 · PR/commit linked
Production note: Most teams hit this during upgrades or environment changes. Roll out with a canary and smoke critical endpoints (health, OpenAPI/docs) before 100%.
@@ -1,30 +1,32 @@
import sys
-from collections.abc import Iterator
-from typing import Any, Protocol
+from collections.abc import Awaitable, Iterator
from starlette.applications import Starlette
from starlette.responses import Response, JSONResponse
from starlette.routing import Route
from starlette.middleware import Middleware
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.requests import Request
class FileLoggingMiddleware(BaseHTTPMiddleware):
def __init__(self, app: Starlette, file_name: str = '') -> None:
super().__init__(app)
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
return await call_next(request)
async def homepage(request):
return JSONResponse({'hello': 'world'})
app = Starlette(debug=True, routes=[Route('/', homepage)],
middleware=[Middleware(FileLoggingMiddleware, file_name='/tmp')])
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Upgrade to fixed release\nUpgrade to version 0.49.3 or later.\nWhen NOT to use: This fix should not be applied if strict type checking is required for middleware.\n\n
Why This Fix Works in Production
- Trigger: error: Argument 1 to "Middleware" has incompatible type "type[AccessLoggerMiddleware]"; expected "type[_MiddlewareClass[[]]]" [arg-type]
- Mechanism: The Middleware type was too strict, causing typing issues with custom middleware implementations
- Why the fix works: Relaxed the strictness on the `Middleware` type to resolve typing issues with custom middleware. (first fixed release: 0.49.3).
- If left unfixed, the same config can fail only in production (env differences), causing startup failures or partial feature outages.
Why This Breaks in Prod
- Shows up under Python 3.10 in real deployments (not just unit tests).
- The Middleware type was too strict, causing typing issues with custom middleware implementations
- Surfaces as: error: Argument 1 to "Middleware" has incompatible type "type[AccessLoggerMiddleware]"; expected "type[_MiddlewareClass[[]]]" [arg-type]
Proof / Evidence
- GitHub issue: #2912
- Fix PR: https://github.com/kludex/starlette/pull/3059
- First fixed release: 0.49.3
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.95
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.52
Verified Execution
We executed the runnable minimal repro in a temporary environment and captured exit codes + logs.
- Status: PASS
- Ran: 2026-02-11T16:52:29Z
- Package: starlette
- Fixed: 0.49.3
- Mode: fixed_only
- Outcome: ok
Logs
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“I'm seeing the same issue here in the Nominatim project after updating to starlette 0.47”
“what version of mypy are you using? have you tried updating to the latest version, or using pyright which generally in my experience is more…”
“I tried with mypy 1.15.0 as well but still same issue.”
“Hit this as well while implementing a pure ASGI middleware using asgiref types. ## MRE ## mypy ## pyright ## Versions * Python: 3.10 *…”
Failure Signature (Search String)
- error: Argument 1 to "Middleware" has incompatible type "type[AccessLoggerMiddleware]"; expected "type[_MiddlewareClass[[]]]" [arg-type]
Error Message
Stack trace
Error Message
-------------
error: Argument 1 to "Middleware" has incompatible type "type[AccessLoggerMiddleware]"; expected "type[_MiddlewareClass[[]]]" [arg-type]
Minimal Reproduction
from starlette.applications import Starlette
from starlette.responses import Response, JSONResponse
from starlette.routing import Route
from starlette.middleware import Middleware
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.requests import Request
class FileLoggingMiddleware(BaseHTTPMiddleware):
def __init__(self, app: Starlette, file_name: str = '') -> None:
super().__init__(app)
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
return await call_next(request)
async def homepage(request):
return JSONResponse({'hello': 'world'})
app = Starlette(debug=True, routes=[Route('/', homepage)],
middleware=[Middleware(FileLoggingMiddleware, file_name='/tmp')])
Environment
- Python: 3.10
What Broke
Mypy raises type errors when using custom middleware after upgrading Starlette.
Why It Broke
The Middleware type was too strict, causing typing issues with custom middleware implementations
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
Upgrade to version 0.49.3 or later.
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Fix reference: https://github.com/kludex/starlette/pull/3059
First fixed release: 0.49.3
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- This fix should not be applied if strict type checking is required for middleware.
Verify Fix
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Did This Fix Work in Your Case?
Quick signal helps us prioritize which fixes to verify and improve.
Prevention
- Add a TLS smoke test that performs a real handshake in CI (include CA bundle validation and hostname checks).
- Alert on handshake failures by error string and endpoint to catch cert/CA changes quickly.
Version Compatibility Table
| Version | Status |
|---|---|
| 0.49.3 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.