From 6f94154b9ec2033b80b8c2207051e7591459de50 Mon Sep 17 00:00:00 2001 From: Lars Date: Sat, 28 Mar 2026 07:39:53 +0100 Subject: [PATCH] fix: Add error logging to Phase 0b placeholder calculation wrappers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: All _safe_* functions were silently catching exceptions and returning 'nicht verfügbar', making it impossible to debug why calculations fail. Solution: Add detailed error logging with traceback to all 4 wrapper functions: - _safe_int(): Logs function name, exception type, message, full stack trace - _safe_float(): Same logging - _safe_str(): Same logging - _safe_json(): Same logging Now when placeholders return 'nicht verfügbar', the backend logs will show: - Which placeholder function failed - What exception occurred - Full stack trace for debugging Example log output: [ERROR] _safe_int(goal_progress_score, uuid): ModuleNotFoundError: No module named 'calculations' Traceback (most recent call last): ... This will help identify if issue is: - Missing calculations module import - Missing data in database - Wrong column names - Calculation logic errors --- backend/placeholder_resolver.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/backend/placeholder_resolver.py b/backend/placeholder_resolver.py index 1d5cf56..6ef4959 100644 --- a/backend/placeholder_resolver.py +++ b/backend/placeholder_resolver.py @@ -477,6 +477,7 @@ def _safe_int(func_name: str, profile_id: str) -> str: Returns: String representation of integer value or 'nicht verfügbar' """ + import traceback try: # Import calculations dynamically to avoid circular imports from calculations import scores, body_metrics, nutrition_metrics, activity_metrics, recovery_metrics, correlation_metrics @@ -522,6 +523,8 @@ def _safe_int(func_name: str, profile_id: str) -> str: result = func(profile_id) return str(int(result)) if result is not None else 'nicht verfügbar' except Exception as e: + print(f"[ERROR] _safe_int({func_name}, {profile_id}): {type(e).__name__}: {e}") + traceback.print_exc() return 'nicht verfügbar' @@ -537,6 +540,7 @@ def _safe_float(func_name: str, profile_id: str, decimals: int = 1) -> str: Returns: String representation of float value or 'nicht verfügbar' """ + import traceback try: from calculations import body_metrics, nutrition_metrics, activity_metrics, recovery_metrics, scores @@ -577,6 +581,8 @@ def _safe_float(func_name: str, profile_id: str, decimals: int = 1) -> str: result = func(profile_id) return f"{result:.{decimals}f}" if result is not None else 'nicht verfügbar' except Exception as e: + print(f"[ERROR] _safe_float({func_name}, {profile_id}): {type(e).__name__}: {e}") + traceback.print_exc() return 'nicht verfügbar' @@ -584,6 +590,7 @@ def _safe_str(func_name: str, profile_id: str) -> str: """ Safely call calculation function and return string value or fallback. """ + import traceback try: from calculations import body_metrics, nutrition_metrics, activity_metrics, scores, correlation_metrics @@ -609,6 +616,8 @@ def _safe_str(func_name: str, profile_id: str) -> str: result = func(profile_id) return str(result) if result is not None else 'nicht verfügbar' except Exception as e: + print(f"[ERROR] _safe_str({func_name}, {profile_id}): {type(e).__name__}: {e}") + traceback.print_exc() return 'nicht verfügbar' @@ -616,6 +625,7 @@ def _safe_json(func_name: str, profile_id: str) -> str: """ Safely call calculation function and return JSON string or fallback. """ + import traceback try: import json from calculations import scores, correlation_metrics @@ -647,6 +657,8 @@ def _safe_json(func_name: str, profile_id: str) -> str: else: return json.dumps(result, ensure_ascii=False) except Exception as e: + print(f"[ERROR] _safe_json({func_name}, {profile_id}): {type(e).__name__}: {e}") + traceback.print_exc() return '{}'