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
- Make metadata.name in the request body identical to the {name} segment of the request URL
- Fix client templating so URL and body derive the name from the same source value
- 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
- Build the URL and the body from a single name variable
- Add a client-side assertion that body.metadata.name equals the path name before every apply
- For renames, apply to the new-name URL (this endpoint never renames objects)
- Cover the client apply helper with a unit test asserting URL/body consistency
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Forbidden: namespace does not match
- Invalid request body
- Forbidden: cannot register node name '%s' with client cert '
- IP version is incorrect
- provider ID number cannot be empty
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/d7c1e6e8fb018e98.
Report an issue: GitHub.