API gibt 500-Fehler zurück? REST-API-Probleme systematisch debuggen
Systematische REST-API-Debugging-Anleitung. CORS-Fehler, 500/502/503-Fehler, Timeouts, Authentifizierungsprobleme.
Kurzfassung
Wenn Ihre REST-API 500-Fehler liefert, gehen Sie in dieser Reihenfolge vor: Fehler reproduzieren, die fehlerhafte Komponente isolieren und den Request mithilfe von Logs und curl durch den gesamten Stack nachverfolgen. Die meisten 500-Fehler entstehen durch nicht abgefangene Exceptions, fehlgeschlagene Datenbankverbindungen oder falsch konfigurierte Umgebungsvariablen. Schauen Sie zuerst in die Server-Logs — dort steht fast immer die Antwort.
Voraussetzungen
- Terminal-Zugang zum Server (SSH oder direkt)
curlinstalliert (auf allen gaengigen Betriebssystemen verfuegbar)- Zugriff auf Server-Logs (Anwendungs- und Webserver-Logs)
- Optional: Postman oder HTTPie
- Grundlegendes Verstaendnis von HTTP und JSON
Schritt 1: Systematisches Vorgehen — Reproduzieren, Isolieren, Nachverfolgen
Reproduzieren
Bevor Sie irgendetwas debuggen, brauchen Sie einen zuverlaessigen Weg, den Fehler auszuloesen. Dokumentieren Sie den exakten Request, der fehlschlaegt:
# Den fehlerhaften Request speichern, um ihn wiederholen zu koennen
curl -v -X POST https://api.example.com/v1/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer IHR_TOKEN" \
-d '{"name": "Test", "email": "test@example.com"}' \
2>&1 | tee /tmp/api-debug.log
Stellen Sie sich folgende Fragen: Tritt der Fehler jedes Mal auf? Nur bei bestimmten Daten? Nur zu bestimmten Uhrzeiten? Sporadische Fehler deuten haeufig auf Ressourcenknappheit oder Race Conditions hin.
Isolieren
Grenzen Sie ein, welche Komponente den Fehler verursacht. Ein typischer REST-API-Stack hat mehrere Schichten:
Client → DNS → Load Balancer → Reverse Proxy (Nginx) → App-Server → Datenbank
Testen Sie jede Schicht einzeln. Antwortet Nginx? Kann der App-Server die Datenbank erreichen?
# Pruefen, ob Nginx ueberhaupt antwortet
curl -I https://api.example.com/health
# App-Server direkt testen (Reverse Proxy umgehen)
curl -I http://localhost:3000/health
# Datenbankverbindung vom App-Server aus pruefen
mysql -u appuser -p -h db-host -e "SELECT 1;"
# oder fuer PostgreSQL
psql -U appuser -h db-host -c "SELECT 1;"
Nachverfolgen
Verfolgen Sie den Request durch jede Schicht. Aktivieren Sie voruebergehend ausfuehrliches Logging und nutzen Sie Request-IDs, falls Ihre Anwendung diese unterstuetzt:
# Eigene Request-ID mitschicken, um den Request in den Logs zu finden
curl -v -X GET https://api.example.com/v1/orders \
-H "X-Request-ID: debug-12345" \
-H "Authorization: Bearer IHR_TOKEN"
Durchsuchen Sie anschliessend die Logs aller Dienste nach dieser ID.
Schritt 2: Server-Logs lesen
Logs sind Ihr wichtigstes Debugging-Werkzeug. Wo sie liegen, haengt von Ihrem Setup ab:
systemd-Dienste (journalctl)
# Logs eines bestimmten Dienstes anzeigen, neueste zuerst
journalctl -u my-api-service -n 100 --no-pager
# Logs in Echtzeit verfolgen (wie tail -f)
journalctl -u my-api-service -f
# Nach Zeitraum filtern
journalctl -u my-api-service --since "2024-01-15 14:00" --until "2024-01-15 15:00"
# Nur Fehlermeldungen anzeigen
journalctl -u my-api-service -p err -n 50
Docker-Container
# Die letzten 200 Zeilen der Container-Logs anzeigen
docker logs --tail 200 my-api-container
# Logs in Echtzeit mit Zeitstempeln verfolgen
docker logs -f --timestamps my-api-container
# Bei Docker-Compose-Setups
docker-compose logs -f --tail=100 api
PM2 (Node.js)
# Logs einer bestimmten App anzeigen
pm2 logs my-api --lines 100
# Nur Fehler-Logs anzeigen
pm2 logs my-api --err --lines 50
# Logs leeren und neu starten
pm2 flush my-api
Klassische Log-Dateien
# Nginx-Fehlerlog
tail -f /var/log/nginx/error.log
# Nginx-Zugriffslog — nach 500-Fehlern filtern
grep ' 500 ' /var/log/nginx/access.log | tail -20
# Anwendungslogs (uebliche Speicherorte)
tail -f /var/log/myapp/error.log
tail -f /var/log/syslog | grep myapp
Schritt 3: Testen mit curl
curl ist das vielseitigste Werkzeug zum API-Debugging. Verinnerlichen Sie diese Muster:
Grundlegende Requests mit ausfuehrlicher Ausgabe
# GET-Request mit allen Headers (-v fuer verbose)
curl -v https://api.example.com/v1/users
# Nur Response-Headers anzeigen
curl -I https://api.example.com/v1/users
# Response-Headers UND Body anzeigen
curl -i https://api.example.com/v1/users
POST-Requests mit JSON-Daten
# POST mit JSON-Body
curl -X POST https://api.example.com/v1/users \
-H "Content-Type: application/json" \
-d '{"name": "Maria Mueller", "email": "maria@example.com", "role": "admin"}'
# POST mit Daten aus einer Datei
curl -X POST https://api.example.com/v1/import \
-H "Content-Type: application/json" \
-d @payload.json
# PUT-Request zum Aktualisieren einer Ressource
curl -X PUT https://api.example.com/v1/users/42 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOi..." \
-d '{"name": "Maria Schmidt"}'
Verbindungsprobleme analysieren
# Timing-Informationen anzeigen
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nVerbindung: %{time_connect}s\nTLS: %{time_appconnect}s\nErstes Byte: %{time_starttransfer}s\nGesamt: %{time_total}s\nHTTP-Code: %{http_code}\n" https://api.example.com/v1/health
# Zu einer bestimmten IP aufloesen (DNS umgehen)
curl --resolve api.example.com:443:10.0.0.5 https://api.example.com/v1/health
# Eigenes Timeout setzen (5 Sekunden)
curl --max-time 5 --connect-timeout 3 https://api.example.com/v1/slow-endpoint
Schritt 4: HTTP-Statuscodes verstehen
Jeder Statuscode erzaehlt eine bestimmte Geschichte. Hier ist, was sie in der Praxis bedeuten:
400 Bad Request
Bedeutung: Der Server kann den Request nicht verarbeiten, weil die Syntax fehlerhaft oder die Daten ungueltig sind.
Haeufige Ursachen: Fehlende Pflichtfelder, falsche Datentypen, ungueltige JSON-Syntax, Feldlaengen-Limits ueberschritten.
# Wird wahrscheinlich einen 400-Fehler zurueckgeben — ungueltiges JSON
curl -X POST https://api.example.com/v1/users \
-H "Content-Type: application/json" \
-d '{name: "Anfuehrungszeichen am Key fehlen"}'
401 Unauthorized
Bedeutung: Die Authentifizierung fehlt oder ist ungueltig. Der Server weiss nicht, wer Sie sind.
Haeufige Ursachen: Fehlender Authorization-Header, abgelaufenes Token, falscher API-Key.
403 Forbidden
Bedeutung: Die Authentifizierung war erfolgreich, aber Sie haben keine Berechtigung fuer diese Aktion. Der Server weiss, wer Sie sind — aber Sie duerfen das nicht.
Haeufige Ursachen: Unzureichende Rolle oder Berechtigung, IP-Allowlist-Beschraenkung, Ressource gehoert einem anderen Benutzer.
404 Not Found
Bedeutung: Die angeforderte Ressource existiert unter dieser URL nicht.
Haeufige Ursachen: Tippfehler in der URL, Ressource wurde geloescht, falsches API-Versions-Praefix, fehlender Trailing Slash.
500 Internal Server Error
Bedeutung: Der Server ist auf einen unerwarteten Zustand gestossen. Dies ist immer ein serverseitiger Fehler.
Haeufige Ursachen: Nicht abgefangene Exceptions, Null-Pointer-Fehler, fehlende Umgebungsvariablen, Datenbankverbindungsfehler, Speichermangel.
502 Bad Gateway
Bedeutung: Der Reverse Proxy (Nginx, Apache) hat eine ungueltige Antwort vom vorgelagerten App-Server erhalten.
Haeufige Ursachen: App-Server abgestuerzt, App-Server laeuft nicht, falscher Upstream-Port in der Proxy-Konfiguration.
503 Service Unavailable
Bedeutung: Der Server kann voruebergehend keine Anfragen verarbeiten.
Haeufige Ursachen: Server startet gerade, Wartungsmodus, Ueberlastung, Abhaengigkeit (Datenbank) ist nicht erreichbar.
504 Gateway Timeout
Bedeutung: Der Reverse Proxy hat zu lange auf eine Antwort vom Upstream-Server gewartet.
Haeufige Ursachen: Langsame Datenbankabfragen, haengende externe API-Aufrufe, zu niedrig konfigurierte Proxy-Timeouts.
Schritt 5: CORS-Fehler beheben
Cross-Origin Resource Sharing (CORS)-Fehler treten nur im Browser auf. Wenn Ihre API mit curl funktioniert, aber im Browser mit "CORS policy"-Fehlern scheitert, muss die Loesung serverseitig erfolgen.
CORS-Probleme erkennen
# Einen CORS-Preflight-Request simulieren
curl -v -X OPTIONS https://api.example.com/v1/users \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type, Authorization"
# Pruefen Sie die Antwort auf folgende Header:
# Access-Control-Allow-Origin: https://app.example.com
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
# Access-Control-Allow-Headers: Content-Type, Authorization
Nginx-CORS-Konfiguration
# /etc/nginx/conf.d/api.conf
server {
listen 443 ssl;
server_name api.example.com;
location /v1/ {
# CORS-Header
add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Request-ID" always;
add_header Access-Control-Max-Age 86400 always;
# Preflight-Requests behandeln
if ($request_method = OPTIONS) {
return 204;
}
proxy_pass http://localhost:3000;
}
}
Express.js-CORS-Konfiguration
const cors = require('cors');
app.use(cors({
origin: ['https://app.example.com', 'https://staging.example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization', 'X-Request-ID'],
credentials: true,
maxAge: 86400
}));
Wichtig: Verwenden Sie niemals Access-Control-Allow-Origin: * zusammen mit credentials: true. Browser lehnen diese Kombination ab. Geben Sie immer die exakte Origin an.
Schritt 6: Timeout-Probleme
Timeouts koennen auf jeder Schicht auftreten. Identifizieren Sie, wo das Timeout passiert:
# Antwortzeiten aufgeschluesselt messen
curl -w "\n---Zeitmessung---\nDNS: %{time_namelookup}s\nVerbindung: %{time_connect}s\nTLS: %{time_appconnect}s\nErstes Byte: %{time_starttransfer}s\nGesamt: %{time_total}s\n" \
-o /dev/null -s https://api.example.com/v1/reports/generate
Wenn time_starttransfer hoch, aber time_connect niedrig ist, braucht der Server lange fuer die Verarbeitung. Ist time_connect hoch, liegt ein Netzwerk- oder DNS-Problem vor.
Gaengige Timeout-Konfigurationen
# Nginx — Proxy-Timeout fuer langsame Endpunkte erhoehen
location /v1/reports/ {
proxy_pass http://localhost:3000;
proxy_read_timeout 120s;
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
}
# Node.js — Server-Timeout erhoehen
const server = app.listen(3000);
server.setTimeout(120000); // 120 Sekunden
Schritt 7: JWT- und OAuth-Debugging
Authentifizierungsprobleme gehoeren zu den haeufigsten API-Fehlern. So untersuchen Sie Tokens:
JWT-Token inspizieren
Ein JWT besteht aus drei Teilen, getrennt durch Punkte: Header.Payload.Signatur. Die ersten beiden Teile lassen sich ohne Secret dekodieren:
# JWT-Payload im Terminal dekodieren (kein Secret noetig)
echo 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMiwiZXhwIjoxNTE2MjQyNjIyfQ.signature' \
| cut -d'.' -f2 \
| base64 -d 2>/dev/null | python3 -m json.tool
Pruefen Sie auf diese haeufigen Probleme:
- exp — Ist das Token abgelaufen? Vergleichen Sie mit dem aktuellen Unix-Zeitstempel:
date +%s - iss — Stimmt der Aussteller mit dem ueberein, was der Server erwartet?
- aud — Stimmt der Audience-Claim mit Ihrer API ueberein?
- scope/roles — Enthaelt das Token die benoetigten Berechtigungen?
Sie koennen Tokens auch auf jwt.io einfuegen, um sie visuell zu analysieren (fuegen Sie niemals Produktions-Tokens mit sensiblen Daten ein).
OAuth-Flows testen
# Neues Token mit Client-Credentials-Grant anfordern
curl -X POST https://auth.example.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=IHRE_CLIENT_ID" \
-d "client_secret=IHR_CLIENT_SECRET" \
-d "scope=read write"
# Das zurueckgegebene access_token verwenden
curl -H "Authorization: Bearer ACCESS_TOKEN_HIER" \
https://api.example.com/v1/protected-resource
Schritt 8: Postman und HTTPie
HTTPie — Die benutzerfreundliche curl-Alternative
# Installation
brew install httpie # macOS
apt install httpie # Ubuntu/Debian
# GET-Request (formatiert JSON automatisch)
http GET https://api.example.com/v1/users Authorization:"Bearer TOKEN"
# POST mit JSON (Content-Type muss nicht angegeben werden)
http POST https://api.example.com/v1/users name="Maria" email="maria@example.com"
# Request- und Response-Headers anzeigen
http -v POST https://api.example.com/v1/users name="Maria"
# Antwort in Datei speichern
http --download https://api.example.com/v1/export
Postman-Tipps
- Nutzen Sie Environments, um zwischen Entwicklung, Staging und Produktion zu wechseln, ohne Requests aendern zu muessen
- Speichern Sie Tokens in Umgebungsvariablen: legen Sie
{{base_url}}und{{token}}an - Verwenden Sie die Console (View → Show Postman Console), um Roh-Request/Response-Daten einschliesslich Weiterleitungen einzusehen
- Nutzen Sie Pre-request Scripts, um abgelaufene OAuth-Tokens automatisch zu erneuern
- Verwenden Sie den Tests-Tab, um die Antwortstruktur automatisch zu validieren
Schnellreferenz zur Fehlerbehebung
| Symptom | Wahrscheinliche Ursache | Erster Schritt |
|---|---|---|
| 500 auf allen Endpunkten | App-Absturz, fehlende Umgebungsvariable, DB nicht erreichbar | Anwendungslogs pruefen |
| 500 auf einem Endpunkt | Nicht abgefangene Exception in dieser Route | Logs nach Stack-Trace durchsuchen |
| 502 Bad Gateway | App-Server laeuft nicht | systemctl status myapp |
| 504 Gateway Timeout | Langsame Abfrage oder externer Aufruf | curl-Timing und DB-Slow-Log pruefen |
| CORS-Fehler im Browser | Fehlende Response-Header | Mit curl OPTIONS-Request testen |
| 401 trotz gueltigem Token | Token abgelaufen oder falsches Audience | JWT dekodieren, exp-Claim pruefen |
| Funktioniert in Postman, scheitert im Browser | CORS- oder Cookie-Problem | Preflight-Antwort ueberpruefen |
| Sporadische 500-Fehler | Ressourcenknappheit, Race Condition | Speicher/CPU ueberwachen, Connection Pool pruefen |
Vorbeugung und Best Practices
- Strukturiertes Logging: Verwenden Sie JSON-Logs mit Request-IDs, Zeitstempeln und Kontext. Tools wie ELK oder Loki machen das Durchsuchen trivial.
- Health-Check-Endpunkte: Implementieren Sie
/health- und/ready-Endpunkte, die Datenbankverbindungen und die Verfuegbarkeit von Abhaengigkeiten pruefen. - Fehlerbehandlungs-Middleware: Fangen Sie alle nicht behandelten Exceptions auf Framework-Ebene ab. Geben Sie in Produktion niemals Stack-Traces an Clients weiter — loggen Sie sie serverseitig und liefern Sie eine generische Fehlermeldung mit einer Request-ID zurueck.
- Monitoring und Alerting: Richten Sie Alarme fuer Anstiege der 5xx-Fehlerrate ein. Ein ploetzlicher Anstieg von 500-Fehlern nach einem Deployment bedeutet: erst zurueckrollen, dann debuggen.
- Request-Validierung: Validieren Sie Eingaben an der API-Grenze mithilfe von Schema-Validierung (z.B. Joi, Zod, JSON Schema). Liefern Sie klare 400-Fehler mit einer Beschreibung, was genau falsch ist.
- Timeouts ueberall: Setzen Sie explizite Timeouts fuer Datenbankabfragen, externe HTTP-Aufrufe und Proxy-Konfigurationen. Verlassen Sie sich nie auf Standardwerte — sie sind oft zu hoch oder gar nicht gesetzt.
- Retry mit Backoff: Implementieren Sie beim Aufruf externer Dienste exponentielles Backoff. Wiederholen Sie niemals bei 4xx-Fehlern — nur bei 5xx und Netzwerkfehlern.
Experten-Hilfe gebraucht?
Ursache nicht gefunden? Ich debugge live. €49.
Jetzt buchen — €49100% Geld-zurück-Garantie