kubernetes/kops · error

Forbidden: name does not match

Error message

Forbidden: name does not match

What it means

The apply endpoint requires that the metadata.name in the request body equals the {name} path parameter. If they differ, the server returns HTTP 403 rather than silently renaming or creating a duplicate object. This keeps apply semantics unambiguous: the URL identifies exactly the object being written.

Source

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

	var input api.DiscoveryEndpoint
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		log.Info("invalid request body", "error", err)
		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 {
		log.Info("Forbidden: cannot register node name", "name", input.ObjectMeta.Name, "clientID", 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 name in body matches the URL
	if input.ObjectMeta.Name != name {
		log.Info("Forbidden: name does not match", "name", input.ObjectMeta.Name, "expected", name)
		http.Error(w, "Forbidden: name does not match", http.StatusForbidden)
		return
	}

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

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

	// Return the created object
	s.writeJSON(w, http.StatusCreated, input)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Make metadata.name in the request body identical to the {name} segment of the request URL
  2. Fix client templating so URL and body derive the name from the same source value
  3. If a rename is intended, apply to the new-name URL (and delete the old object); this endpoint never renames

Example fix

// before
name := "node-a"
url := base + "/discoveryendpoints/" + name
body := DiscoveryEndpoint{ObjectMeta: metav1.ObjectMeta{Name: "node-b"}}
// after
name := "node-a"
url := base + "/discoveryendpoints/" + name
body := DiscoveryEndpoint{ObjectMeta: metav1.ObjectMeta{Name: name}}
Defensive patterns

Strategy: validation

Validate before calling

// Go client: body name must equal the URL name before applying
func validateNameMatch(ep *DiscoveryEndpoint, urlName string) error {
    if ep.ObjectMeta.Name != urlName {
        return fmt.Errorf("metadata.name %q != URL name %q", ep.ObjectMeta.Name, urlName)
    }
    return nil
}

Type guard

func nameMatchesPath(ep *DiscoveryEndpoint, urlName string) bool {
    return ep.ObjectMeta.Name == urlName
}

Try / catch

resp, err := client.ApplyDiscoveryEndpoint(ctx, universe, ns, name, ep)
if err != nil {
    var httpErr *HTTPError
    if errors.As(err, &httpErr) && httpErr.StatusCode == http.StatusForbidden && httpErr.Body == "Forbidden: name does not match" {
        // set ep.ObjectMeta.Name = name (the URL value) and retry once
    }
    return err
}

Prevention

When it happens

Trigger: Apply (POST/PUT) to .../discoveryendpoints/{name} where the decoded DiscoveryEndpoint body has metadata.name different from the {name} in the URL path (including empty body name while the URL name is non-empty).

Common situations: Client builds the URL from one variable and the body from a stale/renamed value; kubectl-style apply where the manifest name was edited but the URL is derived from the old resource name; hand-rolled HTTP clients that forget to sync path and body.

Understand the failure class

Related errors


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