409 Conflict
Verwendung
Wenn ein 409-Conflict-Fehler eintrifft, ist die Anfrage gültig, kann aber wegen einer Zustandsabweichung nicht abgeschlossen werden. Beispielsweise antwortet der Client auf einen inzwischen gelöschten Beitrag, und die Zielressource befindet sich nicht mehr in einem kompatiblen Zustand. Der Server gibt diesen Status zurück, um den Konflikt zu signalisieren.
Hinweis
409 Conflict bedeutet, dass die Anfrage wohlgeformt ist, aber mit dem aktuellen Ressourcenzustand kollidiert (gleichzeitige Aktualisierung, doppelte Erstellung). 422 Unprocessable Content bedeutet, dass der Anfragerumpf syntaktisch gültig, aber semantisch ungültig ist (fehlgeschlagene Validierungsregeln). 400 Bad Request bedeutet, dass die Anfrage selbst fehlerhaft ist (nicht parsbarer Rumpf, ungültige Header). Bei 409 geht es um Zustandskonflikte, bei 422 um Validierung, bei 400 um Syntax.
Vom Client wird erwartet, dass er den Nachrichtenrumpf prüft, um zu bestimmen, wie das Problem zu lösen ist. Im Fall einer Antwort auf einen gelöschten Beitrag entscheidet sich der Client dafür, die Anfrage aufzugeben, den früheren Thread wiederherzustellen oder einen neuen Thread zu erstellen, der den früheren Text zitiert. Diese Aktion liegt vollständig in der Verantwortung des Clients und folgt den vom Server festgelegten Anforderungen oder Richtlinien.
SEO-Auswirkung
Suchmaschinen wie Google indexieren eine URL nicht, die einen 409-Status zurückgibt. Zuvor indexierte URLs, die diesen Statuscode zurückgeben, werden aus den Suchergebnissen entfernt.
Beispiel
Der Client versucht, einen bestehenden Blogbeitrag mit “ID = 111” mit einem “like” zu markieren. Der Server antwortet, um mitzuteilen, dass der Beitrag eingefroren wurde und keine Antworten oder Markierungen mehr akzeptiert.
Anfrage
POST /blog/update?postid=111&flag=like HTTP/1.1
Host: example.com
Antwort
HTTP/1.1 409 Conflict
Content-Type: text/html
Content-Length: 288
<html>
<head>
<title>Blog Entry Frozen</title>
</head>
<body>
<p>This post has been marked read-only. To post
a reply or tag, change the status and try
again.</p>
</body>
</html>
Behebung
Eine 409 Conflict bedeutet, dass die Anfrage mit dem aktuellen Zustand der Ressource auf dem Server kollidiert.
Rufen Sie vor einem erneuten Versuch den aktuellen Ressourcenzustand ab. Senden Sie eine GET-Anfrage, um die neueste Version zu erhalten. Der Ressourcenzustand hat sich geändert, seit der Client die Daten zuletzt gelesen hat. Vergleichen Sie das zurückgegebene ETag oder Versionsfeld mit dem Wert, den der Client vorhält.
Verwenden Sie bedingte Header, um Konflikte zu erkennen. Fügen Sie bei PUT- und PATCH-Anfragen If-Match mit dem aktuellen ETag-Wert hinzu. Der Server weist die Anfrage ab, sobald das ETag nicht mehr übereinstimmt, und verhindert so blindes Überschreiben. Dieses Muster wird optimistische Nebenläufigkeitskontrolle genannt.
PUT /api/resource/42 HTTP/1.1
If-Match: "abc123"
Content-Type: application/json
{"name": "updated value"}
Der Server antwortet mit 409, wenn ein anderer Client die Ressource zwischen dem GET und dem PUT verändert hat.
Führen Sie Änderungen zusammen oder implementieren Sie eine Konfliktlösungslogik. Vergleichen Sie die vom Client beabsichtigten Änderungen mit dem aktuellen Serverzustand. Wenden Sie eine Merge-Strategie an: Last-Write-Wins, feldweises Zusammenführen oder eine Rückfrage an den Endbenutzer, um Unterschiede aufzulösen. APIs mit einem Versions- oder Revisionsfeld in der Nutzlast verlangen vom Client, die aktuelle Versionsnummer in der Aktualisierungsanfrage mitzusenden.
Lösen Sie Konflikte durch doppelte Ressourcen auf. Beim Erstellen einer Ressource mit POST oder PUT gibt der Server 409 zurück, wenn bereits eine Ressource mit derselben eindeutigen Kennung existiert. Prüfen Sie vor dem Erstellen auf vorhandene Einträge und verwenden Sie einen Idempotency-Key, um doppelte Erstellungen bei Wiederholungsversuchen zu vermeiden.
Behandeln Sie Konflikte auf Datenbankebene. Anwendungsserver mit einer Datenbank im Hintergrund geben 409 zurück, wenn eine Unique-Constraint, eine Foreign-Key-Constraint oder eine Sperre auf Zeilenebene die Operation verhindert. Der Antwortrumpf enthält häufig den Namen der konkreten Constraint. Lösen Sie den zugrunde liegenden Datenkonflikt (doppelter Schlüssel, fehlender übergeordneter Datensatz, nebenläufige Transaktion), bevor Sie es erneut versuchen.
Bei Versionsverwaltungssystemen holen Sie die neueste Version und wenden die Änderungen erneut an. Rufen Sie die neueste Revision ab, gleichen Sie die Unterschiede ab und senden Sie die Aktualisierung erneut. Git-basierte APIs (GitHub, GitLab) geben 409 zurück, wenn ein Push mit Änderungen im Upstream kollidiert.
Prüfen Sie den Antwortrumpf auf Konfliktdetails. Der Server fügt typischerweise Informationen bei, die die Abweichung erklären: das konfliktbehaftete Feld, den aktuellen Wert oder die erwartete Version. Nutzen Sie diese Daten, um den richtigen Lösungsweg zu bestimmen.
Implementieren Sie eine Wiederholungslogik mit Zustandsaktualisierung. Bauen Sie für automatisierte Clients eine Wiederholungsschleife: den neuesten Ressourcenzustand abrufen, die beabsichtigte Änderung erneut anwenden und erneut senden. Ergänzen Sie exponentielles Backoff, um den Server unter hoher Nebenläufigkeit nicht zu überlasten.
Code-Referenzen
.NET
HttpStatusCode.Conflict
Rust
http::StatusCode::CONFLICT
Rails
:conflict
Go
http.StatusConflict
Symfony
Response::HTTP_CONFLICT
Python3.5+
http.HTTPStatus.CONFLICT
Java
java.net.HttpURLConnection.HTTP_CONFLICT
Apache HttpComponents Core
org.apache.hc.core5.http.HttpStatus.SC_CONFLICT
Angular
@angular/common/http/HttpStatusCode.Conflict