kubernetes/kops · error

parsing reference %q: %v

Error message

parsing reference %q: %v

What it means

CopyImage.Run wraps the failure of go-containerregistry's name.ParseReference on the SOURCE image string. ParseReference validates that the string is a well-formed container image reference (registry host, repository path, optional tag/digest). kOps re-wraps the underlying parse error as "parsing reference %q: %v" so the invalid source image is named in the message.

Source

Thrown at pkg/assets/assetcopy/copyimage.go:43

	"github.com/google/go-containerregistry/pkg/v1/types"
	"k8s.io/klog/v2"
)

// CopyImage copies a docker image from a source registry, to a target registry,
// typically used for highly secure clusters.
type CopyImage struct {
	Name        string
	SourceImage string
	TargetImage string
}

func (e *CopyImage) Run() error {
	source := e.SourceImage
	target := e.TargetImage

	sourceRef, err := name.ParseReference(source)
	if err != nil {
		return fmt.Errorf("parsing reference %q: %v", source, err)
	}

	targetRef, err := name.ParseReference(target)
	if err != nil {
		return fmt.Errorf("parsing reference for %q: %v", target, err)
	}

	options := []remote.Option{remote.WithAuthFromKeychain(authn.DefaultKeychain)}

	desc, err := remote.Get(sourceRef, options...)
	if err != nil {
		return fmt.Errorf("fetching %q: %v", source, err)
	}

	targetDesc, err := remote.Get(targetRef, options...)
	if err == nil && desc.Digest.String() == targetDesc.Digest.String() {
		klog.Infof("no need to copy image from %v to %v", sourceRef, targetRef)
		return nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Fix the SourceImage value in the kops cluster spec (spec.assets) to a valid image reference like 'registry.k8s.io/kops/kube-apiserver:v1.x.y'.
  2. Test the string with `go-containerregistry`'s crane or `name.ParseReference` locally to see the exact grammar complaint.
  3. Check for unexpanded template variables or duplicated slashes/colons in the configured image URL.
  4. If the image has no tag, note ParseReference defaults to :latest; add an explicit tag or digest to be safe.

Example fix

// before
CopyImage{SourceImage: "registry.k8s.io/kops/ kube-apiserver:v1.28.0", TargetImage: "..."}
// after
CopyImage{SourceImage: "registry.k8s.io/kops/kube-apiserver:v1.28.0", TargetImage: "..."}
Defensive patterns

Strategy: validation

Validate before calling

func validImageRef(ref string) bool {
	_, err := name.ParseReference(ref)
	return err == nil
}

if !validImageRef(src.SourceImage) {
	return fmt.Errorf("invalid SourceImage reference: %q", src.SourceImage)
}

Try / catch

var cerr *name.ErrBadName
if errors.As(err, &cerr) {
	log.Printf("bad image reference, fix cluster spec assets: %v", cerr)
} else if err != nil {
	return err
}

Prevention

When it happens

Trigger: CopyImage.Run is called with SourceImage that name.ParseReference rejects: empty string, invalid characters, malformed repository name, a tag/digest that violates the reference grammar (e.g. '!!bad tag', 'registry/repo::tag'), or an invalid registry host (wrong port, underscore in hostname).

Common situations: Misconfigured kops cluster spec ( Assets container / cluster spec assets fields) where the image URL was hand-edited; templated values left unfilled (e.g. '{{ .Image }}'); typo'd registry host like 'registry-1.io//repo'; using ':' or '@' incorrectly in a digest reference.

Related errors


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