kubernetes/kops · error
image %q has no root device name
Error message
image %q has no root device name
What it means
The AMI resolved fine but its RootDeviceName field was empty, so kops cannot generate a root-volume block device mapping for the Karpenter EC2NodeClass. The root device name is required to override the image's root volume instead of attaching an extra volume.
Source
Thrown at upup/pkg/fi/cloudup/template_functions_karpenter.go:399
// karpenterRootDeviceName resolves the root device name of the InstanceGroup image, so
// that the generated block device mapping overrides the image's root volume rather than
// attaching an additional one. The name varies between images (/dev/xvda, /dev/sda1),
// so it has to come from the image itself.
func (tf *TemplateFunctions) karpenterRootDeviceName(image string) (string, error) {
cloud, ok := tf.cloud.(awsup.AWSCloud)
if !ok {
return "", fmt.Errorf("expected an AWS cloud, got %T", tf.cloud)
}
resolved, err := cloud.ResolveImage(image)
if err != nil {
return "", fmt.Errorf("unable to resolve image %q: %w", image, err)
}
if resolved == nil {
return "", fmt.Errorf("unable to resolve image %q: not found", image)
}
rootDeviceName := fi.ValueOf(resolved.RootDeviceName)
if rootDeviceName == "" {
return "", fmt.Errorf("image %q has no root device name", image)
}
return rootDeviceName, nil
}
func (tf *TemplateFunctions) buildKarpenterNodePool(ig *kops.InstanceGroup) (*karpenterNodePool, error) {
labels, err := nodelabels.BuildNodeLabels(tf.Cluster, ig)
if err != nil {
return nil, fmt.Errorf("building node labels for %q: %w", ig.Name, err)
}
labels = karpenterNodePoolTemplateLabels(labels)
template := karpenterNodeClaimTemplate{
Spec: karpenterNodeClaimSpec{
Requirements: tf.karpenterRequirements(ig),
NodeClassRef: karpenterNodeClassRef{
Group: karpenterAWSAPIGroup,
Kind: "EC2NodeClass",
Name: ig.Name,View on GitHub (pinned to 4c8573c808)
Solutions
- Verify the AMI's block device mappings with `aws ec2 describe-images` — rootDeviceName should be set
- Choose a different/standard AMI that declares a root device
- Re-run kops update cluster in case of a transient partial API response
- If it is a custom AMI, rebuild it with a proper root EBS mapping
Defensive patterns
Strategy: validation
Validate before calling
// check rootDeviceName before rendering
img, err := cloud.ResolveImage(image)
if err == nil && img != nil && fi.ValueOf(img.RootDeviceName) == "" {
return fmt.Errorf("AMI %s has no root device mapping", image)
} Try / catch
if err != nil && strings.Contains(err.Error(), "has no root device name") {
return fmt.Errorf("choose an AMI with a defined root device: %w", err)
} Prevention
- Inspect `aws ec2 describe-images` blockDeviceMappings before using a custom AMI
- Prefer standard published AMIs (AL2023, Ubuntu) which always declare a root device
- Rebuild custom AMIs with a proper root EBS mapping
When it happens
Trigger: cloud.ResolveImage returns a non-nil ec2.Image whose RootDeviceName is unset — typically an anomalous/incomplete DescribeImages response or an image with no block device mappings.
Common situations: Rare: corrupted/edge-case AMI metadata, custom-built images lacking rootDeviceName in their block device mappings, or AWS API returning a partial image record.
Related errors
- unable to resolve image %q: not found
- image name specification not recognized: %q
- error listing images: %v
- could not find Image for %q
- unable to resolve image %q: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/4a6913d20146e778.
Report an issue: GitHub.