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.
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
- http status
- 400 Bad Request
- aborted
- bad response status
- can't locate source or destination in command arguments
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/4c7a211adf81c74f.
Report an issue: GitHub.
Appendix: 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)