rancher/rancher · warning

cannot read request body: %v

Error message

cannot read request body: %v

What it means

checkCredentials does io.ReadAll(req.Body) and returns HTTP 400 'cannot read request body: %v' when the read itself fails. The handler never got a parsable body: the connection reset mid-upload, the body was truncated by a proxy, or a size limit was enforced upstream.

Source

Thrown at pkg/api/norman/customization/alibaba/handler.go:192

		}
		writer.Write(serialized)
	case "alibabaImageSupportedInstanceTypes":
		if serialized, errCode, err = describeImageSupportedInstanceTypes(capabilities, req); err != nil {
			logrus.Debugf("[alibaba-handler] error call describeImageSupportedInstanceTypes: %v", err)
			util.ReturnHTTPError(writer, req, errCode, err.Error())
			return
		}
		writer.Write(serialized)
	default:
		handleErr(writer, httperror.NotFound.Status, fmt.Errorf("invalid endpoint %v", resourceType))
	}
}

func (h *handler) checkCredentials(req *http.Request) (int, error) {
	cred := &Capabilities{}
	raw, err := io.ReadAll(req.Body)
	if err != nil {
		return http.StatusBadRequest, fmt.Errorf("cannot read request body: %v", err)
	}

	if err = json.Unmarshal(raw, &cred); err != nil {
		return http.StatusBadRequest, fmt.Errorf("cannot parse request body: %v", err)
	}

	if cred.RegionID == "" {
		cred.RegionID = defaultRegion
	}
	if cred.AccessKeyID == "" {
		return http.StatusBadRequest, fmt.Errorf("must provide access key ID")
	}
	if cred.AccessKeySecret == "" {
		return http.StatusBadRequest, fmt.Errorf("must provide access key secret")
	}

	client, err := CreateECSClient(cred.AccessKeyID, cred.AccessKeySecret, cred.RegionID)
	if err != nil {

View on GitHub (pinned to 932558d4e6)

Solutions

  1. Retry the request - read failures are usually transient transport errors
  2. Shrink the payload; only accessKeyId/accessKeySecret/regionId are needed
  3. Raise proxy body-size and timeout limits on the path to Rancher
  4. Confirm the client sends Content-Length and completes the body (no dangling chunked stream)

Example fix

// before
await fetch(url, {method: 'POST', body: hugeBlob}); // proxy truncates -> 400
// after
await fetch(url, {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({accessKeyId: id, accessKeySecret: secret})
});
Defensive patterns

Strategy: try-catch

Try / catch

try {
	const res = await fetch(url, {method: 'POST', body: JSON.stringify(payload)});
	if (!res.ok) {
		const msg = await res.text();
		if (msg.includes('cannot read request body')) {
			// transport truncated the upload - safe to retry once
		}
	}
} catch (e) {
	// network-level failure before the server saw a body: retry idempotently
}

Prevention

When it happens

Trigger: Client aborts or network reset during upload; reverse proxy (nginx client_max_body_size, Traefik limits) truncating; very large or chunked bodies the server rejects; keep-alive recycled mid-request.

Common situations: Flaky client networks; aggressive proxy body-size caps; load balancer idle timeouts on slow uploads.

Related errors


AI-assisted analysis of rancher/rancher@932558d4e6 (2026-08-16). Data as JSON: /api/errors/175e5ba444ae8585. Report an issue: GitHub.