kubernetes/kops · warning

Invalid request body

Error message

Invalid request body

What it means

handleCreateDiscoveryEndpoint decodes the POST body into api.DiscoveryEndpoint with encoding/json. If the body is not valid JSON or does not match the DiscoveryEndpoint schema, decoding fails and the server returns 400 'Invalid request body'. The detailed decode error is not included in the response.

Source

Thrown at discovery/pkg/discovery/server.go:156

		TypeMeta: metav1.TypeMeta{Kind: "DiscoveryEndpointList", APIVersion: "discovery.kops.k8s.io/v1alpha1"},
	}

	for _, ep := range endpoints {
		if ns == "" || ep.ObjectMeta.Namespace == ns {
			resp.Items = append(resp.Items, *ep)
		}
	}

	s.writeJSON(w, http.StatusOK, resp)
}

func (s *Server) handleCreateDiscoveryEndpoint(w http.ResponseWriter, r *http.Request, userInfo *UserInfo) {
	universeID := r.PathValue("universe")
	ns := r.PathValue("namespace")

	var input api.DiscoveryEndpoint
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		http.Error(w, "Invalid request body", http.StatusBadRequest)
		return
	}

	// Validation: ensure the name matches the clientID from the cert
	if input.ObjectMeta.Name != "" && input.ObjectMeta.Name != userInfo.ClientID {
		http.Error(w, fmt.Sprintf("Forbidden: cannot register node name '%s' with client cert '%s'", input.ObjectMeta.Name, userInfo.ClientID), http.StatusForbidden)
		return
	}

	// Validation: ensure the namespace in body matches the URL
	if input.ObjectMeta.Namespace != ns {
		http.Error(w, "Forbidden: namespace does not match", http.StatusForbidden)
		return
	}

	if err := s.Store.UpsertDiscoveryEndpoint(r.Context(), universeID, &input); err != nil {
		http.Error(w, fmt.Sprintf("Error creating endpoint: %v", err), http.StatusInternalServerError)
		return

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Validate the JSON body with a parser/linter before sending (e.g. jq, python -m json.tool).
  2. Confirm you are sending a single DiscoveryEndpoint object, not YAML or a List.
  3. Set Content-Type: application/json and ensure the full body is transmitted.
  4. Unmarshal locally against api.DiscoveryEndpoint to see the exact decode error Go would return.

Example fix

// before: sending YAML
body := []byte("metadata:\n  name: node1\n")
// after: valid JSON
body := []byte(`{"metadata":{"name":"node1","namespace":"default"}}`)
Defensive patterns

Strategy: validation

Validate before calling

var probe interface{}
if err := json.Unmarshal(body, &probe); err != nil {
    return fmt.Errorf("body is not valid JSON: %w", err)
}
var ep api.DiscoveryEndpoint
if err := json.Unmarshal(body, &ep); err != nil {
    return fmt.Errorf("body does not match DiscoveryEndpoint schema: %w", err)
}

Try / catch

resp, err := client.Post(url, "application/json", bytes.NewReader(body))
if err == nil && resp.StatusCode == http.StatusBadRequest {
    return fmt.Errorf("server rejected body; validate JSON with: json.Unmarshal(body, &DiscoveryEndpoint{})")
}

Prevention

When it happens

Trigger: POST to /{universe}/apis/discovery.kops.k8s.io/v1alpha1/namespaces/{namespace}/discoveryendpoints with: empty body, malformed JSON (syntax errors), wrong Content-Type handling, YAML instead of JSON, or fields of the wrong type.

Common situations: Clients sending YAML manifests unconverted; truncated bodies; template rendering bugs producing invalid JSON; sending a List where an item is expected; type mismatches (string vs int in spec).

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/00df88c22dd109bf. Report an issue: GitHub.