"""Map exceptions to consistent JSON error responses.""" from __future__ import annotations import logging from flask import Flask, current_app, jsonify from werkzeug.exceptions import HTTPException, RequestEntityTooLarge from ..exceptions import AppError logger = logging.getLogger(__name__) def _error_body(message: str, status: int, detail: str = "", project_id: str = ""): body = {"message": message, "isError": True} # Internal details go to clients only for client errors, or when DEBUG is on. if detail and (status < 500 or current_app.config["SETTINGS"].debug): body["error"] = detail if project_id: body["project_id"] = project_id # lets support correlate with the server logs return jsonify(body), status def register_error_handlers(app: Flask) -> None: @app.errorhandler(AppError) def handle_app_error(e: AppError): if e.status_code >= 500: logger.error("Project %s failed: %s", e.project_id or "-", e.detail or e) return _error_body(e.public_message, e.status_code, e.detail, e.project_id) @app.errorhandler(RequestEntityTooLarge) def handle_too_large(e): limit = current_app.config["SETTINGS"].max_upload_mb return _error_body(f"❌ File too large (max {limit} MB)", 413) @app.errorhandler(Exception) def handle_unexpected(e: Exception): if isinstance(e, HTTPException): # 404/405 etc. keep their normal status return _error_body(e.description or e.name, e.code or 500) logger.exception("Unhandled error") return _error_body("❌ Internal server error", 500, str(e))