Código de status HTTP · Erros do cliente (4xx)
Erro 428 Precondition Required
O erro 428 Precondition Required significa que o servidor só aplica a alteração se o pedido for condicional, geralmente com o cabeçalho If-Match. A causa é um PUT, PATCH ou DELETE enviado sem o ETag que o cliente recebeu na última leitura do recurso.
| Classe | 4xx, Erros do cliente |
|---|---|
| Definido em | RFC 6585 §3 |
| Pode ir para o cache por padrão | Não; a RFC 6585 proíbe caches de armazená-la |
| Pode repetir o pedido | Sim, depois de adicionar If-Match (ou If-Unmodified-Since) com o ETag atual |
| Cabeçalhos relevantes |
|
O que significa o 428
A RFC 6585, seção 3, criou o 428 para evitar o problema da atualização perdida: dois clientes fazem GET do mesmo documento, os dois editam, e o segundo PUT sobrescreve o primeiro sem ninguém perceber. Exigindo If-Match, o servidor obriga cada escrita a provar que está editando a versão mais recente.
A RFC pede que a resposta explique como reenviar e proíbe caches de guardá-la. O 428 é o "faltou a pré-condição"; se a pré-condição veio mas está desatualizada, a resposta certa é 412.
Causas comuns
Se você administra o servidor
- A biblioteca cliente nunca manda cabeçalhos condicionais, porque foi escrita para uma API que não exigia.
- Um proxy ou o próprio cliente descarta o ETag das respostas GET, então não há o que colocar no If-Match.
- Um script atualiza registros com PUT às cegas, sem ler antes.
Como resolver
Se você administra o servidor
- Faça GET do recurso, guarde o cabeçalho ETag da resposta e mande de volta como If-Match na escrita.
- Se a escrita então der 412, alguém alterou o recurso nesse meio tempo: busque de novo, reaplique sua mudança e tente outra vez.
- No servidor, coloque uma explicação curta no corpo do 428 e documente quais métodos exigem If-Match.
Como enviar um 428
app.put('/articles/:id', (req, res) => {
if (!req.get('If-Match')) {
return res.status(428).json({ error: 'Send If-Match with the ETag from your last GET' });
}
// compare If-Match with the current ETag; on mismatch answer 412
});// app/articles/[id]/route.ts
export async function PUT() {
return Response.json(
{ error: 'Send If-Match with the ETag from your last GET' },
{ status: 428 }
);
}mux.HandleFunc("PUT /articles/{id}", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusPreconditionRequired) // 428
w.Write([]byte(`{"error":"Send If-Match with the ETag from your last GET"}`))
})from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.put("/articles/{id}")
def update_article(id: str):
raise HTTPException(status_code=428, detail="Send If-Match with the ETag from your last GET")Costuma ser confundido com
- 428 vs 412
- O 412 significa que você mandou uma pré-condição e ela falhou (o ETag não bate mais); o 428 significa que você não mandou pré-condição nenhuma.
- 428 vs 409
- O 409 relata um conflito que o servidor detectou pela própria lógica; o 428 pede que o cliente torne o conflito detectável mandando If-Match.
Perguntas frequentes
- Como resolver o erro 428 Precondition Required?
- Leia o recurso antes, copie o cabeçalho ETag dessa resposta e reenvie o PUT, PATCH ou DELETE com If-Match: "<esse etag>". Algumas APIs também aceitam If-Unmodified-Since com a data do Last-Modified.
- O que é o problema da atualização perdida?
- Duas pessoas abrem o mesmo registro, as duas editam e o segundo salvamento apaga o primeiro sem aviso. Exigir If-Match transforma o segundo salvamento num 412, e o cliente sabe que precisa recarregar e juntar as mudanças.
- A resposta 428 pode ficar em cache?
- Não. A RFC 6585 determina que respostas 428 não podem ser armazenadas por caches, já que a resposta certa depende dos cabeçalhos de cada pedido.
Revisado em por Arielton Oberek.