Nebula - 3.3.0
Nebula 3.3.0 - Release Notes
What’s New
⚠️ Error Dispatcher & Injection System (Major)
Nebula introduces a flexible injection system for error handlers along with a fully redesigned error dispatch pipeline.
Error handlers can now declare exactly what they need, and Nebula will inject it automatically.
Error Handler Injection
Error handlers now support explicit parameter injection.
Supported parameters:
request- current request objectscope- raw ASGI scopereceive- ASGI receive callablesend- ASGI send callablecode- HTTP status code
Example
@app.error_handler(404)
async def not_found(request, code):
return f"<h1>{code} - {request.path} not found</h1>"Only declared parameters are passed, nothing extra.
⚠️ Important Behavior
- Injection is name-based, not positional
- Only explicitly declared parameters are provided
- Works for both sync and async handlers
- No runtime introspection, everything is cached at registration
Error Dispatcher
Nebula’s internal _dispatch_error system has been completely redesigned.
Key Improvements
-
⚡ Zero overhead at runtime
- No
inspectcalls during request handling
- No
-
🧠 Precomputed handler metadata
- Accepted parameters cached
- Async/sync status cached
-
🔁 Unified execution path
- Same logic for all error handlers
How It Works
- Error occurs (404 / 405 / 500 or
HTTPException) - Matching handler is resolved
- Required parameters are injected
- Handler is executed (sync or async)
- Return value is normalized into a
Response
Strict Signature Validation
Error handlers are now validated at registration time.
Allowed parameters:
{"scope", "receive", "send", "request", "code"}Example (invalid)
@app.error_handler(404)
def handler(foo): # ❌ not allowed
...➡️ Raises:
ExtraArgumentsDetected⚠️ Behavior Note
- Invalid signatures fail early (at startup)
- Prevents runtime bugs and undefined behavior
- Ensures consistent handler contracts
Automatic Response Handling
Error handlers can return any supported type:
-
Response→ used directly -
dict/list→JSONResponse -
str→ auto-detected:- HTML →
HTMLResponse - URL →
RedirectResponse - otherwise →
PlainTextResponse
- HTML →
Example
@app.error_handler(500)
def internal_error(code):
return {"error": "Internal Server Error", "status": code}Request Context Access
Nebula now provides a global request proxy:
from nebula import request
@app.error_handler(500)
def handler():
return f"Error on {request.path}"⚠️ Important Behavior
- Powered by
ContextVar(async-safe) - Only available inside request lifecycle
- Access outside request raises:
RuntimeErrorDefault Error Handlers
Built-in handlers (404, 405, 500) now:
- Use the same injection system
- Follow the same response normalization rules
- Are fully replaceable via
@app.error_handler(...)
Internal Improvements
- Added
_error_handler_paramscache - Added
_error_handler_is_asynccache - Removed runtime
inspectusage from hot path - Improved separation of dispatch and execution
- Optimized error handling performance
⚠️ Breaking Changes
1. Restricted Error Handler Signatures
Old:
def handler(foo, bar): ...New:
def handler(request, code): ...Only supported parameters are allowed.