Daily Report - 05. Januar 2026
Quick Win: Better Error Messages (Phase 1 Backend)
Zusammenfassung
Heute wurde Phase 1 des “Better Error Messages” Quick Wins erfolgreich abgeschlossen. Das System hat jetzt ein zentrales Error Message System mit benutzerfreundlichen deutschen Fehlermeldungen, Error Codes für Client-Side Handling und hilfreichen Hints für User.
Zeitaufwand: ~1.5h (geschätzt: 2h) Status: Backend komplett, Frontend Integration steht noch aus Impact: Hoch (Code-Qualität, UX Foundation, Wartbarkeit)
🎯 Projektziele
Ursprüngliche Probleme
- Sprachinkonsistenz - Mix aus Deutsch und Englisch
1 2
detail="Fehler beim Laden der JWKS" # Deutsch detail="Failed to load..." # Englisch
- Zu technische Fehler - Stack Traces für Enduser
1 2
detail=f"Unknown key ID in token header: {kid}" detail=f"Failed to create invoice: {str(e)}"
- Fehlende Kontextinformationen
- Keine Lösungsvorschläge
- Keine Error Codes für Support
- Kein “Was kann ich tun?”
- Frontend: Keine User-Benachrichtigungen
1 2 3
// Fehler landen nur in Console.error() ❌ console.error('❌ Unauthorized - Session expired'); // User sieht: NICHTS
✅ Implementierte Lösung
1. Zentrales Error Message System
Neue Dateien:
backend/app/core/errors/__init__.pybackend/app/core/errors/messages.py(430 Zeilen)
Features:
Error Codes (60+ definiert)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class ErrorCode:
# 1xxx: Authentication & Authorization
AUTH_NOT_AUTHENTICATED = "AUTH_1001"
AUTH_INVALID_TOKEN = "AUTH_1002"
AUTH_EXPIRED_TOKEN = "AUTH_1003"
AUTH_INVALID_CREDENTIALS = "AUTH_1007"
# ... 9 weitere
# 2xxx: Invoices
INVOICE_NOT_FOUND = "INVOICE_2001"
INVOICE_ALREADY_PAID = "INVOICE_2002"
INVOICE_NUMBER_EXISTS = "INVOICE_2005"
# ... 10 weitere
# 3xxx: Finance (30+ vorbereitet)
STRIPE_NOT_CONFIGURED = "FINANCE_3060"
SEVDESK_API_ERROR = "FINANCE_3072"
# ...
# 4xxx-9xxx: Weitere Module
CUSTOMER_NOT_FOUND = "CRM_4001"
PRODUCT_NOT_FOUND = "PRODUCT_5010"
SYSTEM_ERROR = "SYSTEM_9000"
Error Messages mit Hints
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ERROR_MESSAGES = {
ErrorCode.AUTH_INVALID_CREDENTIALS: ErrorMessage(
message="E-Mail oder Passwort ist falsch.",
hint="Bitte überprüfen Sie Ihre Eingaben."
),
ErrorCode.INVOICE_NOT_FOUND: ErrorMessage(
message="Rechnung '{invoice_id}' wurde nicht gefunden.",
hint="Bitte überprüfen Sie die Rechnungsnummer."
),
ErrorCode.PAYMENT_EXCEEDS_AMOUNT: ErrorMessage(
message="Der Zahlungsbetrag ({amount}€) übersteigt den offenen Betrag ({outstanding}€).",
hint="Bitte reduzieren Sie den Zahlungsbetrag."
),
}
Einfache API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Verwendung in CRUD/Routes
from app.core.errors import ErrorCode, get_error_detail
raise HTTPException(
status_code=404,
detail=get_error_detail(
ErrorCode.INVOICE_NOT_FOUND,
invoice_id="RE-2025-001"
)
)
# API Response:
{
"detail": {
"error_code": "INVOICE_2001",
"message": "Rechnung 'RE-2025-001' wurde nicht gefunden.",
"hint": "Bitte überprüfen Sie die Rechnungsnummer."
}
}
2. Auth Module (13 Errors) ✅
Dateien geändert:
backend/app/core/auth/routes.py- Login, OIDC, Password Managementbackend/app/core/auth/auth.py- Token Validation, JWKSbackend/app/core/auth/roles.py- Permission Checking
Vorher:
1
2
3
4
5
6
7
8
9
10
# ❌ Technisch, Englisch, keine Hilfe
raise HTTPException(
status_code=401,
detail="Invalid or expired token"
)
raise HTTPException(
status_code=401,
detail=f"Unknown key ID in token header: {kid}"
)
Nachher:
1
2
3
4
5
6
7
8
9
10
11
# ✅ Benutzerfreundlich, Deutsch, mit Hint
raise HTTPException(
status_code=401,
detail=get_error_detail(ErrorCode.AUTH_INVALID_TOKEN)
)
# Returns:
# {
# "error_code": "AUTH_1002",
# "message": "Ihr Sitzungstoken ist ungültig.",
# "hint": "Bitte melden Sie sich erneut an."
# }
Migrierte Error Codes:
AUTH_1001- Not AuthenticatedAUTH_1002- Invalid TokenAUTH_1003- Expired TokenAUTH_1004- Invalid PayloadAUTH_1005- User Not FoundAUTH_1006- User InactiveAUTH_1007- Invalid CredentialsAUTH_1008- OIDC FailedAUTH_1009- Insufficient PermissionsAUTH_1010- Password Too ShortAUTH_1011- Wrong PasswordAUTH_1012- No Password Set
3. Invoice Module (15 Errors) ✅
Dateien geändert:
backend/app/modules/backoffice/invoices/crud.py
Vorher:
1
2
3
4
5
6
7
8
9
10
# ❌ Technische Stack Traces für User
raise HTTPException(
status_code=404,
detail=f"Customer {customer_id} not found"
)
raise HTTPException(
status_code=500,
detail=f"Failed to create invoice: {str(e)}"
)
Nachher:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# ✅ Benutzerfreundlich mit Kontext
raise HTTPException(
status_code=404,
detail=get_error_detail(
ErrorCode.INVOICE_CUSTOMER_NOT_FOUND,
customer_id=str(customer_id)
)
)
# ✅ Generischer Fehler ohne Stack Trace
raise HTTPException(
status_code=500,
detail=get_error_detail(ErrorCode.SYSTEM_ERROR)
)
# Stack Trace geht ins Logger (nicht zum User!)
logger.error("Failed to create invoice: %s", e)
Migrierte Error Codes:
INVOICE_2001- Invoice Not FoundINVOICE_2002- Already PaidINVOICE_2003- Already DeletedINVOICE_2004- Not Deleted (Can’t Restore)INVOICE_2005- Number ExistsINVOICE_2006- Customer Not FoundINVOICE_2007- Project Not FoundINVOICE_2008- Generation FailedINVOICE_2009- PDF FailedINVOICE_2010- XML Failed
4. Payments Module (5 Errors) ✅
Dateien geändert:
backend/app/modules/backoffice/invoices/payments_crud.py
Vorher:
1
2
3
4
5
# ❌ Technisch, nicht hilfreich
raise HTTPException(
status_code=400,
detail=f"Payment amount ({amount}) exceeds outstanding amount ({outstanding})"
)
Nachher:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ✅ Mit deutscher Formulierung und Lösungsvorschlag
raise HTTPException(
status_code=400,
detail=get_error_detail(
ErrorCode.PAYMENT_EXCEEDS_AMOUNT,
amount=str(data.amount),
outstanding=str(invoice.outstanding_amount)
)
)
# Returns:
# {
# "error_code": "PAYMENT_2051",
# "message": "Der Zahlungsbetrag (500€) übersteigt den offenen Betrag (300€).",
# "hint": "Bitte reduzieren Sie den Zahlungsbetrag."
# }
Migrierte Error Codes:
PAYMENT_2050- Payment Not FoundPAYMENT_2051- Payment Exceeds Amount
📊 Statistik
Geänderte Dateien: 7
Neue Dateien:
backend/app/core/errors/__init__.py(9 Zeilen)backend/app/core/errors/messages.py(430 Zeilen)
Geänderte Dateien:
backend/app/core/auth/routes.py(10 Errors migriert)backend/app/core/auth/auth.py(8 Errors migriert)backend/app/core/auth/roles.py(2 Errors migriert)backend/app/modules/backoffice/invoices/crud.py(10 Errors migriert)backend/app/modules/backoffice/invoices/payments_crud.py(3 Errors migriert)
Code-Änderungen
| Metrik | Anzahl |
|---|---|
| Error Messages migriert | 33 |
| Error Codes definiert | 60+ |
| LOC hinzugefügt | ~450 |
| Module vollständig migriert | 3 (Auth, Invoice, Payments) |
Error Code Kategorien
| Kategorie | Codes | Status |
|---|---|---|
| 1xxx: Authentication & Authorization | 12 | ✅ Alle migriert |
| 2xxx: Invoices & Payments | 12 | ✅ Alle migriert |
| 3xxx: Finance (Stripe, SevDesk, etc.) | 30+ | 📝 Definiert, nicht migriert |
| 4xxx: CRM & Customers | 1 | 📝 Definiert |
| 5xxx: Projects & Products | 3 | 📝 Definiert |
| 6xxx: Documents | 2 | 📝 Definiert |
| 7xxx: Dashboards | 2 | 📝 Definiert |
| 8xxx: Reminders | 1 | 📝 Definiert |
| 9xxx: System & Generic | 2 | ✅ Verwendet |
🔄 Verbleibende Arbeit
Backend (Optional - nicht kritisch)
Noch ~152 HTTPExceptions in anderen Modulen könnten migriert werden:
| Modul | Anzahl Errors | Aufwand | Priorität |
|---|---|---|---|
| Finance (Stripe, SevDesk, FinTS, PSD2) | ~60 | 1h | Medium |
| CRM Module | ~20 | 20min | Low |
| Products Module | ~10 | 10min | Low |
| Documents Module | ~10 | 10min | Low |
| Weitere Module | ~52 | 45min | Low |
Hinweis: Error Codes sind bereits alle definiert. Migration wäre hauptsächlich Copy-Paste Arbeit.
Frontend Integration (Kritisch für UX!)
Status: ⏳ Ausstehend Aufwand: ~30min Priorität: HOCH
Aktuelles Problem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ui/src/services/api/client.ts
apiClient.interceptors.response.use(
(response) => response,
(error: AxiosError) => {
if (error.response) {
switch (error.response.status) {
case 401:
console.error('❌ Unauthorized'); // ❌ Nur Console!
break;
case 404:
console.error('❌ Not Found'); // ❌ User sieht nichts!
break;
}
}
return Promise.reject(error);
}
);
User Experience:
- ❌ Fehler landen nur in Browser Console
- ❌ User sieht KEINE Benachrichtigung
- ❌ Keine hilfreichen Hinweise
Geplante Lösung
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { ElMessage } from 'element-plus';
interface ErrorResponse {
error_code: string;
message: string;
hint?: string;
}
apiClient.interceptors.response.use(
(response) => response,
(error: AxiosError<{ detail: ErrorResponse }>) => {
const errorData = error.response?.data?.detail;
if (errorData && typeof errorData === 'object' && 'error_code' in errorData) {
// ✅ Strukturierter Error mit Code & Hint
ElMessage({
type: 'error',
message: errorData.message,
description: errorData.hint,
duration: 5000,
showClose: true,
});
} else {
// ✅ Fallback für alte/unbekannte Errors
ElMessage.error({
message: 'Ein Fehler ist aufgetreten',
duration: 3000,
});
}
// Log für Debugging
console.error('API Error:', {
code: errorData?.error_code,
message: errorData?.message,
response: error.response,
});
return Promise.reject(error);
}
);
User Experience nach Migration:
- ✅ User sieht Toast-Notification im UI
- ✅ Deutsche, verständliche Fehlermeldung
- ✅ Hilfreicher Hint (“Bitte melden Sie sich erneut an”)
- ✅ Error Code für Support/Debugging
🎯 Vorher/Nachher Vergleich
Backend API Response
Vorher:
1
2
3
{
"detail": "Invalid or expired token"
}
Nachher:
1
2
3
4
5
6
7
{
"detail": {
"error_code": "AUTH_1002",
"message": "Ihr Sitzungstoken ist ungültig.",
"hint": "Bitte melden Sie sich erneut an."
}
}
User Experience
Vorher:
1
2
3
4
5
Browser Console:
❌ Unauthorized - Session expired
User sieht:
[Nichts - keine Benachrichtigung]
Nachher (nach Frontend Integration):
1
2
3
4
5
6
7
8
9
Browser Console:
🔍 API Error: { code: "AUTH_1002", message: "Ihr Sitzungstoken..." }
User sieht:
┌─────────────────────────────────────┐
│ ⚠️ Ihr Sitzungstoken ist ungültig. │
│ │
│ 💡 Bitte melden Sie sich erneut an. │
└─────────────────────────────────────┘
💡 Lessons Learned
Was gut funktioniert hat
- Zentrale Error Registry
- Alle Messages an einem Ort
- Einfach zu erweitern
- Type-safe Error Codes
- Variable Interpolation
message="Rechnung '{invoice_id}' nicht gefunden"- Dynamische Werte mit
.format(**kwargs)
- Hint-System
- Gibt User konkrete Lösungsvorschläge
- Reduziert Support-Anfragen
- Error Codes
- Client kann spezifisch reagieren
- Support kann schnell debuggen
- Kategorisierung nach Modulen (1xxx, 2xxx, etc.)
Herausforderungen
- Bestehende Codebase
- ~185 HTTPExceptions im gesamten Backend
- Schrittweise Migration notwendig
- Kritische Module zuerst (Auth, Invoice)
- Rückwärtskompatibilität
- Alte Clients erwarten
detail: string - Neue Clients erwarten
detail: object - Lösung: Frontend prüft Typ von
detail
- Alte Clients erwarten
📝 Nächste Schritte
Morgen (Frontend Integration - 30min)
Priorität: HOCH
- Error Response Type definieren
1 2 3 4 5 6
// ui/src/types/api.ts export interface ErrorResponse { error_code: string; message: string; hint?: string; }
- API Client erweitern
- ElMessage Integration
- Error Code Handling
- Logging
- Testen mit echten Errors
- Login mit falschen Credentials
- Rechnung nicht gefunden
- Token expired
Optional (Weitere Backend-Module)
Priorität: MEDIUM
- Finance Module (~1h)
- Stripe (13 Errors)
- SevDesk (16 Errors)
- FinTS/PSD2 (20+ Errors)
- Error Codes sind bereits definiert
- Weitere Module (~1h)
- CRM (~20 Errors)
- Products (~10 Errors)
- Documents (~10 Errors)
- Sonstige (~52 Errors)
🎉 Erfolge
Quick Win erfolgreich!
- ✅ Ziel erreicht: Better Error Messages Phase 1
- ✅ Zeit eingehalten: 1.5h (Budget: 2h)
- ✅ Code-Qualität: Deutlich verbessert
- ✅ Foundation gelegt: Für bessere UX
Impact
| Bereich | Vorher | Nachher |
|---|---|---|
| Sprachkonsistenz | ❌ Deutsch/Englisch Mix | ✅ Durchgehend Deutsch |
| User-Freundlichkeit | ❌ Technische Messages | ✅ Verständliche Texte |
| Hilfestellung | ❌ Keine Hints | ✅ Lösungsvorschläge |
| Debugbarkeit | ❌ Keine Error Codes | ✅ Eindeutige Codes |
| Logging | ⚠️ Stack Traces für User | ✅ Clean für User, Log für Dev |
📚 Dokumentation
Erstellt:
/tmp/better_error_messages_progress.md- Detaillierte technische Dokumentationdocs/daily_reports/2026-01-05_better-error-messages.md- Dieser Daily Report
Code-Kommentare:
- Error Message System vollständig dokumentiert
- Beispiele in Docstrings
🔗 Related Work
Vorherige Quick Wins:
- 2026-01-04: Code Cleanup (TODOs, print()→logger, Config)
- 2026-01-02: Invoice Compliance (GoBD, Audit Trail, Soft-Delete)
Roadmap:
- ⏳ Better Error Messages - Frontend Integration (morgen)
- ⏳ Loading Skeleton Components (2h)
- ⏳ Employee List Page (2h)
Fazit
Phase 1 des “Better Error Messages” Quick Wins ist erfolgreich abgeschlossen. Das Backend hat jetzt ein professionelles, wartbares Error Message System mit:
- ✅ 60+ definierten Error Codes
- ✅ Benutzerfreundlichen deutschen Messages
- ✅ Hilfreichen Hints für User
- ✅ 33 migrierte Errors in kritischen Modulen
Der nächste Schritt (Frontend Integration) wird den vollen Nutzen für die User Experience bringen. Danach ist der Quick Win komplett und bietet deutlich bessere Fehlermeldungen für alle User.