kubernetes/kops · error
ErrAlreadyExists
ErrAlreadyExists
Error message
node already exists
What it means
Reported when matchInstanceGroup returns an error while mapping a discovered ASG to a kops InstanceGroup in getCloudGroups. Note the ASG name is included but the underlying err is discarded, so the actual cause is hidden.
Source
Thrown at pkg/bootstrap/authenticate.go:27
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package bootstrap
import (
"context"
"errors"
"net/http"
"k8s.io/kops/pkg/nodeidentity/clusterapi"
)
var ErrAlreadyExists = errors.New("node already exists")
// Authenticator generates authentication credentials for requests.
type Authenticator interface {
CreateToken(body []byte) (string, error)
}
// VerifyResult is the result of a successfully verified request.
type VerifyResult struct {
// Nodename is the name that this node is authorized to use.
NodeName string
// InstanceGroupName is the name of the kops InstanceGroup this node is a member of.
InstanceGroupName string
// CAPIMachine is the Cluster API Machine object corresponding to this node, if available.
CAPIMachine *clusterapi.Machine
// CertificateNames is the alternate names the node is authorized to use for certificates.View on GitHub (pinned to 4c8573c808)
Solutions
- Inspect the ASG name and re-create/rename the matching kops instance group
- Delete the orphaned/stale ASG that carries the cluster tags but no matching instance group
- Ensure ASG names follow the kops convention <instancegroup>.<clustername>
- Replace the `err` in the message with `%v` wrap to expose the real cause before debugging
Example fix
// before
return nil, fmt.Errorf("error getting instance group for ASG %q", name)
// after
return nil, fmt.Errorf("error getting instance group for ASG %q: %v", name, err) Defensive patterns
Strategy: validation
Validate before calling
for _, asg := range asgs {
if _, err := matchInstanceGroup(aws.ToString(asg.AutoScalingGroupName), cluster.Name, igs); err != nil {
klog.Warningf("skipping unmatchable ASG %q", aws.ToString(asg.AutoScalingGroupName))
}
} Type guard
func matchesClusterASG(name, clusterName string, igs []*kops.InstanceGroup) bool {
return matchInstanceGroup(name, clusterName, igs) == nil
} Try / catch
groups, err := cloud.GetCloudGroups(ctx, cluster, igs, true, nodes)
if err != nil && strings.Contains(err.Error(), "error getting instance group for ASG") {
// extract ASG name from %q and delete or rename the orphaned ASG
name := extractQuoted(err)
cleanupOrphanedASG(name)
} Prevention
- Keep ASG names in the kops convention <instancegroup>.<clustername>
- Remove leftover ASGs from old clusters sharing tags
- Rename instance groups only via kops update, not manually
- Improve the error to include the underlying err for debuggability
When it happens
Trigger: matchInstanceGroup errors when the ASG name's machine-type suffix cannot be parsed against the cluster's instance groups — e.g. ASG naming like `nodes.foo-1234` does not correspond to any kops instance group role/spec pattern.
Common situations: ASG was renamed or created manually with kops cluster tags but a non-standard name; stale ASGs left from a previous cluster with the same name; instance group renamed in the kops spec while old ASGs still exist.
Related errors
- DIGITALOCEAN_ACCESS_TOKEN is required
- the image for the hook exec action not set
- IP version is incorrect
- DIGITALOCEAN_ACCESS_TOKEN is required
- provider ID cannot be empty
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/9a7eb5b8c445da4f.
Report an issue: GitHub.