skills/error-handling-backend-python/SKILL.md
Implement consistent Python FastAPI error handling with global exception handlers, custom exceptions, and structured error responses. Use when: building exception handlers, creating domain exceptions, mapping errors to HTTP status codes, or structured error logging with structlog.
npx skillsauth add congiuluc/my-awesome-copilot error-handling-backend-pythonInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
ApiResponse error envelopedomain/exceptions/ApiResponse envelope with error details — never expose stack tracesAppException (base)
├── NotFoundException → 404
├── ValidationException → 400
├── ConflictException → 409
├── UnauthorizedException → 401
├── ForbiddenException → 403
└── BusinessRuleException → 422
class AppException(Exception):
"""Base exception for all domain errors."""
def __init__(self, message: str, status_code: int = 500) -> None:
self.message = message
self.status_code = status_code
super().__init__(message)
class NotFoundException(AppException):
def __init__(self, message: str = "Resource not found") -> None:
super().__init__(message, status_code=404)
class ValidationException(AppException):
def __init__(self, message: str = "Validation failed") -> None:
super().__init__(message, status_code=400)
class ConflictException(AppException):
def __init__(self, message: str = "Resource conflict") -> None:
super().__init__(message, status_code=409)
import structlog
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
logger = structlog.get_logger()
def register_exception_handlers(app: FastAPI) -> None:
@app.exception_handler(AppException)
async def app_exception_handler(request: Request, exc: AppException) -> JSONResponse:
logger.warning("domain_error", error=exc.message, status=exc.status_code)
return JSONResponse(
status_code=exc.status_code,
content={"success": False, "data": None, "error": exc.message},
)
@app.exception_handler(Exception)
async def unhandled_exception_handler(request: Request, exc: Exception) -> JSONResponse:
logger.error("unhandled_error", error=str(exc), exc_info=True)
return JSONResponse(
status_code=500,
content={"success": False, "data": None, "error": "An unexpected error occurred."},
)
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(min=1, max=10))
async def call_external_service() -> dict:
async with httpx.AsyncClient() as client:
response = await client.get("https://api.example.com/data")
response.raise_for_status()
return response.json()
error level for unexpected errorsExceptionApiResponse envelope — never raw error bodiestools
Build VS Code extensions with TypeScript. Covers extension anatomy, activation events, commands, tree views, webview panels, language features, testing, and publishing. Use when: creating a new VS Code extension, adding commands/views/providers, building webview UIs, implementing language server features, testing extensions, or packaging for the marketplace.
development
Track implementations, features, bugs, and releases in a versioning document. Use when: adding a commit, completing a feature, fixing a bug, or preparing a release. Automatically updates CHANGELOG.md following Keep a Changelog format and Semantic Versioning.
development
Write frontend tests using Vitest and React Testing Library. Use when: testing React components, hooks, user interactions, form submissions, accessibility assertions, or mocking API services.
development
Write Angular frontend tests using Jasmine, Karma, and Angular TestBed. Use when: testing Angular components, services, pipes, directives, user interactions, form submissions, accessibility assertions, or mocking HTTP services.