kubernetes/kops · error

image is required

Error message

image is required

What it means

buildKarpenterAMITerms converts the configured image spec into Karpenter EC2NodeClass AMI terms. An empty/whitespace-only image string is rejected with 'image is required', since no AMI selector can be produced without an image.

Solutions

  1. Set the image field in the instance group spec to an ami-*, ssm:<parameter>, <name>, or <owner>/<name> value
  2. If using env substitution in your config, verify the variable actually resolves
  3. Re-run `kops update cluster` after setting the image

Example fix

// before
image: ""
// after
image: ami-0abcdef1234567890
Defensive patterns

Strategy: validation

Validate before calling

// ensure image is set before rendering
if strings.TrimSpace(ig.Spec.Image) == "" {
	return fmt.Errorf("instance group %s: image must be set", ig.Name)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "image is required") {
	return fmt.Errorf("set image field for the karpenter instance group")
}

Prevention

When it happens

Trigger: Calling buildKarpenterEC2NodeClass (or using the template function in a template) with the image field empty after strings.TrimSpace — e.g. image set to "" or only spaces in the instance group/config.

Common situations: Omitting the image field in a Karpenter instance group spec; a config templating step leaving the placeholder blank; yaml key present but value empty after env-substitution failed.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at upup/pkg/fi/cloudup/template_functions_karpenter.go:459

	}
	if ig.Spec.MaxSize != nil {
		spec.Limits = &karpenterNodePoolLimits{Nodes: strconv.FormatInt(int64(*ig.Spec.MaxSize), 10)}
	}

	return &karpenterNodePool{
		APIVersion: karpenterNodePoolAPIGroup + "/v1",
		Kind:       "NodePool",
		Metadata: karpenterObjectMeta{
			Name: ig.Name,
		},
		Spec: spec,
	}, nil
}

func buildKarpenterAMITerms(image string) ([]karpenterAMITerm, error) {
	image = strings.TrimSpace(image)
	if image == "" {
		return nil, fmt.Errorf("image is required")
	}
	if strings.Contains(image, "://") {
		return nil, fmt.Errorf("image %q must be ami-*, ssm:<parameter>, <name>, or <owner>/<name>", image)
	}
	if strings.HasPrefix(image, "ami-") {
		return []karpenterAMITerm{{ID: image}}, nil
	}
	if strings.HasPrefix(image, "ssm:") {
		parameter := strings.TrimPrefix(image, "ssm:")
		if parameter == "" {
			return nil, fmt.Errorf("ssm image parameter is required")
		}
		return []karpenterAMITerm{{SSMParameter: parameter}}, nil
	}

	tokens := strings.SplitN(image, "/", 2)
	if len(tokens) == 1 {
		return []karpenterAMITerm{{Name: image, Owner: "self"}}, nil

View on GitHub (pinned to 4c8573c808)