{"record":{"id":"eb0cb7005cf1e8fd","repo":"openfaas/faas","slug":"error-unmarshalling-request-body","errorCode":null,"errorMessage":"Error unmarshalling request body","messagePattern":"Error unmarshalling request body","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"gateway/scaling/ranges.go","lineNumber":54,"sourceCode":"\t\tif r.Method != http.MethodPost {\n\t\t\thttp.Error(w, \"Only POST is allowed\", http.StatusMethodNotAllowed)\n\t\t\treturn\n\t\t}\n\n\t\tif r.Body == nil {\n\t\t\thttp.Error(w, \"Error reading request body\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tbody, err := io.ReadAll(r.Body)\n\t\tif err != nil {\n\t\t\thttp.Error(w, \"Error reading request body\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tscaleRequest := types.ScaleServiceRequest{}\n\t\tif err := json.Unmarshal(body, &scaleRequest); err != nil {\n\t\t\thttp.Error(w, \"Error unmarshalling request body\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tif scaleRequest.Replicas < 1 {\n\t\t\tscaleRequest.Replicas = 1\n\t\t}\n\n\t\tif scaleRequest.Replicas > DefaultMaxReplicas {\n\t\t\tscaleRequest.Replicas = DefaultMaxReplicas\n\t\t}\n\n\t\tupstreamReq, _ := json.Marshal(scaleRequest)\n\t\t// Restore the io.ReadCloser to its original state\n\t\tr.Body = io.NopCloser(bytes.NewBuffer(upstreamReq))\n\n\t\tnext.ServeHTTP(w, r)\n\t}\n}","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/openfaas/faas/blob/8d803bf9e2655aec6a60fd0e25b392839f96af95/gateway/scaling/ranges.go#L36-L72","documentation":"The scale endpoint decodes the body into types.ScaleServiceRequest with json.Unmarshal (gateway/scaling/ranges.go:54); invalid JSON yields 400 'Error unmarshalling request body'. The expected payload is a JSON object such as {\"service\":\"fn\",\"replicas\":3}, and replicas must be a JSON number — a quoted \"3\" fails to decode into the int field.","triggerScenarios":"Posting YAML, form-encoded data (replicas=4) or plain text; truncated JSON from shell quoting mistakes; sending replicas as a string (\"replicas\":\"3\"); trailing commas or comments in hand-written JSON.","commonSituations":"curl -d without proper quoting on shells; CI scripts templating JSON that breaks on special characters; clients generating JSON by string concatenation instead of a serializer.","solutions":["Send well-formed JSON with a numeric replicas field: curl -X POST -H 'Content-Type: application/json' -d '{\"replicas\":3}' .../system/scale-function/myfn","Build the body with a real JSON serializer (encoding/json, jq -n, json.dumps) instead of concatenation","Validate the payload client-side (jq . or a schema check) before sending","Inspect the raw request in a debug proxy to spot truncation"],"exampleFix":"# before\ncurl -X POST -d replicas=4 http://gw:8080/system/scale-function/myfn\n\n# after\ncurl -X POST -H 'Content-Type: application/json' -d '{\"replicas\":4}' http://gw:8080/system/scale-function/myfn","handlingStrategy":"validation","validationCode":"payload, err := json.Marshal(struct {\n    Replicas int `json:\"replicas\"`\n}{Replicas: 4})\nif err != nil {\n    return err // never hand-write the JSON body\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Marshal scale requests with encoding/json or jq -n instead of string templates","Assert replicas is a JSON number, not a string, in test fixtures","Validate request bodies with jq before curl -d @file"],"tags":["json","scaling","validation","http"],"backgroundTag":null,"analyzedSha":"8d803bf9e2655aec6a60fd0e25b392839f96af95","analyzedAt":"2026-08-16T00:12:29.759Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}