kubernetes/kops · error

parsing reference for %q: %v

Error message

parsing reference for %q: %v

What it means

Same parse failure as the source-side error but for the TARGET image: name.ParseReference rejected e.TargetImage inside CopyImage.Run. The wrapper text is "parsing reference for %q: %v" so you know the destination registry/repository string, not the source, is malformed.

Source

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

// 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
	}

	switch desc.MediaType {
	case types.OCIImageIndex, types.DockerManifestList:
		// Handle indexes separately.

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Correct TargetImage in the kops cluster spec to a valid reference, e.g. 'myregistry.example.com/kops/kube-apiserver:v1.28.0'.
  2. Remove any URL scheme (https://) and credentials from the target string; only host[:port]/repo[:tag][@digest] is allowed.
  3. Verify no template placeholders remain unexpanded in the target value.
  4. Sanity-check with `crane digest <target>` to confirm the reference parses and is reachable.

Example fix

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

Strategy: validation

Validate before calling

func validTargetRef(ref string) bool {
	if ref == "" || strings.Contains(ref, "://") {
		return false
	}
	_, err := name.ParseReference(ref)
	return err == nil
}

if !validTargetRef(target.TargetImage) {
	return fmt.Errorf("invalid TargetImage reference: %q", target.TargetImage)
}

Try / catch

if err != nil {
	var bad *name.ErrBadName
	if errors.As(err, &bad) {
		return fmt.Errorf("target image reference %q is not a valid OCI reference: %w", targetImage, err)
	}
	return err
}

Prevention

When it happens

Trigger: CopyImage.Run called with TargetImage that violates the container reference grammar: empty value, illegal characters, malformed tag/digest suffix, or invalid registry host (bad port, underscore, scheme prefix like 'https://').

Common situations: Typo in the target registry host in the cluster spec assets config; including a URL scheme ('https://myregistry/repo') which is not part of a reference; copying a source URL verbatim into the target field when the target registry has a different repository path/port; empty target because the private-registry asset value was never set for highly secure clusters.

Related errors


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