juicedata/juicefs · error
POST required
Error message
POST required
What it means
The sync cluster worker HTTP endpoint (/stats) in pkg/sync/cluster.go only accepts POST requests and replies 'POST required' with status 400 for any other method. This endpoint receives statistics pushed by peer workers during distributed juicefs sync jobs.
Source
Thrown at pkg/sync/cluster.go:287
base := withoutSize(o)
if base.Size() > multipartCheckpointThreshold && (nsize == base.Size() || nsize == markChecksum) {
if cp := checkpointMgr.GetMultipartCheckpoint(base.Key(), base.Size(), base.Mtime()); cp != nil {
objs[i] = withMultipart(o, cp)
}
}
}
}
d, err := marshalObjects(objs)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
logger.Debugf("send %d objects(%s) to %s", len(objs), humanize.IBytes(uint64(total)), req.RemoteAddr)
_, _ = w.Write(d)
})
mux.HandleFunc("/stats", func(w http.ResponseWriter, req *http.Request) {
if req.Method != "POST" {
http.Error(w, "POST required", http.StatusBadRequest)
return
}
d, err := io.ReadAll(req.Body)
if err != nil {
logger.Errorf("read: %s", err)
return
}
var r Stat
err = json.Unmarshal(d, &r)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
updateStats(&r)
srcDelayDelMu.Lock()
srcDelayDel = append(srcDelayDel, r.DelayDelDir...)
srcDelayDelMu.Unlock()
if checkpointMgr != nil {View on GitHub (pinned to c9a67b23e8)
Solutions
- Use POST when querying the /stats endpoint: curl -X POST http://host:port/stats
- Reconfigure health checks to use POST, or point them at a different endpoint that accepts GET
- If using curl, add -X POST or --data '' to force the POST method
Example fix
// before curl http://127.0.0.1:8999/stats // after curl -X POST http://127.0.0.1:8999/stats
Defensive patterns
Strategy: validation
Validate before calling
req, _ := http.NewRequest(http.MethodPost, baseURL+"/stats", nil) // ensure req.Method == http.MethodPost before Do()
Type guard
func isPost(r *http.Request) bool { return r.Method == http.MethodPost } Try / catch
resp, err := client.Do(req)
if err != nil { return err }
if resp.StatusCode == http.StatusBadRequest { /* wrong method: retry as POST */ } Prevention
- Always use POST for sync worker /stats endpoints
- Do not point GET-based health checks at the sync worker HTTP port
- Read the handler registration (mux.HandleFunc("/stats"...)) to see accepted methods
When it happens
Trigger: Issuing a GET (or PUT/DELETE) request to http://<worker>:<port>/stats on a sync worker's HTTP port; health-check probes configured with GET against this endpoint.
Common situations: Operators probing worker liveness with a browser or curl (defaults to GET); monitoring systems doing GET-based health checks against the sync cluster port.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/4c7a211adf81c74f.
Report an issue: GitHub.