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
- Resend the POST with a JSON body containing job_id
- Ensure the client serializes the request body before sending
- 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
- Always serialize a JSON body before POSTing
- Never send bare -X POST without -d in curl
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
- 2xx codes should not be exceptions. Got status code
- A VPC network must be provided to use a private endpoint.
- An invalid input " " was specified in "fields".
- An unsupported sink was specified
- " " argument must be specified.
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)