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

  1. Use POST when querying the /stats endpoint: curl -X POST http://host:port/stats
  2. Reconfigure health checks to use POST, or point them at a different endpoint that accepts GET
  3. 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

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.