apache/beam · error

empty request body

Error message

empty request body

What it means

HTTP 400 error returned by the Prism web UI's jobCancelHandler when a POST /jobs/cancel-style request has a completely empty body. It is caught after reading the body succeeds but before JSON parsing, distinguishing 'nothing sent' from 'malformed JSON sent'.

Solutions

  1. Resend the POST with a JSON body containing job_id
  2. Ensure the client serializes the request body before sending
  3. Set Content-Type: application/json on the request

Example fix

// before
curl -X POST http://localhost:8083/jobs/cancel
// after
curl -X POST -H 'Content-Type: application/json' -d '{"job_id":"job-123"}' http://localhost:8083/jobs/cancel
Defensive patterns

Strategy: validation

Validate before calling

payload := fmt.Sprintf(`{"job_id":%q}`, jobID)
if len(payload) == 0 { return errors.New("cancel payload is empty") }

Prevention

When it happens

Trigger: POSTing to the cancel endpoint with zero-length body, e.g. curl -X POST with no -d/--data option.

Common situations: curl calls that forget the -d flag; HTTP clients that send POST without a body; tests hitting the endpoint without payloads.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/d374f4b3cb4878cb. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/runners/prism/internal/web/web.go:394

type cancelJobRequest struct {
	JobID string `json:"job_id"`
}

func (h *jobCancelHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var cancelRequest *cancelJobRequest
	if r.Method != http.MethodPost {
		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
		return
	}
	body, err := io.ReadAll(r.Body)
	if err != nil {
		err = fmt.Errorf("could not read request body: %w", err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	if len(body) == 0 {
		http.Error(w, "empty request body", http.StatusBadRequest)
		return
	}
	if err := json.Unmarshal(body, &cancelRequest); err != nil {
		err = fmt.Errorf("error parsing JSON: %s of request: %w", body, err)
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Forward JobId from POST body avoids direct json Unmarshall on composite types containing protobuf message types.
	resp, err := h.Jobcli.Cancel(r.Context(), &jobpb.CancelJobRequest{
		JobId: cancelRequest.JobID,
	})
	if err != nil {
		statusCode := status.Code(err)
		httpCode := http.StatusInternalServerError
		if c, ok := grpcToHttpCodes[statusCode]; ok {
			httpCode = c
		}

View on GitHub (pinned to 12126d8942)