kubernetes/kops · error
Forbidden: namespace does not match
Error message
Forbidden: namespace does not match
What it means
handleCreateDiscoveryEndpoint validates that the namespace in the request body's ObjectMeta matches the {namespace} path segment. A mismatch (including an empty or missing body namespace) is rejected with 403 'Forbidden: namespace does not match'. Note the body namespace must be set exactly, since an empty body namespace will not equal the URL namespace.
Source
Thrown at discovery/pkg/discovery/server.go:168
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
}
// Return the created object
s.writeJSON(w, http.StatusCreated, input)
}
func (s *Server) handleApplyDiscoveryEndpoint(w http.ResponseWriter, r *http.Request, userInfo *UserInfo) {
ctx := r.Context()
log := klog.FromContext(ctx)
universeID := r.PathValue("universe")
ns := r.PathValue("namespace")View on GitHub (pinned to 4c8573c808)
Solutions
- Set metadata.namespace in the body to exactly the namespace in the URL path.
- Fix the URL to use the namespace the object belongs in.
- Ensure your manifest template populates metadata.namespace.
- Client-side check: if body.Namespace != ns, fix before sending.
Example fix
// before
body := []byte(`{"metadata":{"name":"node1"}}`) // namespace missing
// after
body := []byte(`{"metadata":{"name":"node1","namespace":"default"}}`) Defensive patterns
Strategy: validation
Validate before calling
if body.Namespace != urlNamespace {
return fmt.Errorf("body namespace %q != URL namespace %q", body.Namespace, urlNamespace)
} Prevention
- Always set metadata.namespace explicitly in the payload
- Derive body namespace from the same variable used to build the URL
- Add a client-side pre-send assertion comparing body vs URL namespace
When it happens
Trigger: POST to .../namespaces/{ns}/discoveryendpoints where the JSON body's metadata.namespace is different, empty, or omitted; client templated the manifest for another namespace.
Common situations: Applying a manifest generated for namespace 'kube-system' against a 'default' namespace URL; forgetting metadata.namespace entirely in the payload; copy-pasted manifests.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Forbidden: name does not match
- namespace was not provided for namespace-scoped object %v
- Invalid request body
- Forbidden: cannot register node name '%s' with client cert '
- error querying namespace %q: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/d50b209257752c8d.
Report an issue: GitHub.