GoogleContainerTools/skaffold · error

parsing reference %q: %w

Error message

parsing reference %q: %w

What it means

parseReference wraps go-containerregistry's name.ParseReference failure as "parsing reference %q". It is the shared entry point used by AddRemoteTag, getRemoteImage, and getRemoteIndex, so any malformed image reference anywhere in the remote-image flow surfaces through this error.

Source

Thrown at pkg/skaffold/docker/remote.go:170

// IsInsecure tests if an image is pulled from an insecure registry; default is false
func IsInsecure(ref name.Reference, insecureRegistries map[string]bool) bool {
	return insecureRegistries[ref.Context().Registry.Name()]
}

// insecureTransportOption allows untrusted certificates.
func insecureTransportOption() remote.Option {
	transport := remote.DefaultTransport.(*http.Transport).Clone()
	transport.TLSClientConfig = &tls.Config{
		InsecureSkipVerify: true, //nolint: gosec
	}
	return remote.WithTransport(transport)
}

func parseReference(s string, cfg Config, opts ...name.Option) (name.Reference, error) {
	ref, err := name.ParseReference(s, opts...)
	if err != nil {
		return nil, fmt.Errorf("parsing reference %q: %w", s, err)
	}

	if IsInsecure(ref, cfg.GetInsecureRegistries()) {
		ref, err = name.ParseReference(s, name.Insecure)
		if err != nil {
			log.Entry(context.TODO()).Warnf("error getting insecure registry: %s\nremote references may not be retrieved", err.Error())
		}
	}

	return ref, nil
}

type digester interface {
	Digest() (v1.Hash, error)
}

func digest(d digester) (string, error) {
	h, err := d.Digest()

View on GitHub (pinned to a1189de023)

Solutions

  1. Print/log the reference exactly as passed (it's quoted with %q to expose whitespace/empties).
  2. Validate the string: lowercase alphanumerics, optional registry host, optional :tag or @sha256:digest — test with `crane digest <ref>` locally.
  3. Strip scheme prefixes and trim whitespace before calling.
  4. Ensure image name templates/values resolve before invoking Skaffold commands.
  5. Use fully-qualified names consistently (registry/repo:tag) to avoid ambiguity errors.

Example fix

// before
image := os.Getenv("IMAGE") // " GCR.io/Proj/App "
idx, err := docker.RetrieveRemoteConfig(image, ...)
// after
image = strings.ToLower(strings.TrimSpace(os.Getenv("IMAGE")))
if image == "" { return errors.New("IMAGE env var not set") }
idx, err := docker.RetrieveRemoteConfig(image, ...)
Defensive patterns

Strategy: validation

Validate before calling

func validateImageRef(s string) error {
	s = strings.ToLower(strings.TrimSpace(s))
	s = strings.TrimPrefix(strings.TrimPrefix(s, "https://"), "http://")
	if s == "" { return errors.New("empty image reference") }
	_, err := name.ParseReference(s, name.WeakValidation)
	return err
}

Type guard

func isParsableReference(s string) bool {
	_, err := name.ParseReference(strings.TrimSpace(s), name.WeakValidation)
	return err == nil
}

Try / catch

if err := validateImageRef(image); err != nil { return err }
if _, err := docker.RetrieveRemoteConfig(image, cfg, platform); err != nil {
	if strings.Contains(err.Error(), "parsing reference") {
		return fmt.Errorf("image ref %q malformed: use [registry/]repo[:tag|@digest], lowercase, no scheme", image)
	}
	return err
}

Prevention

When it happens

Trigger: An image string passed to any remote lookup fails name.ParseReference: empty string, uppercase characters, invalid registry/repotag syntax, scheme prefix, or (in the insecure re-parse path) a reference that still fails validation with name.Insecure.

Common situations: Templated image names left unresolved ("{{.IMAGE}}"); uppercase repo names; trailing whitespace or newlines from env vars; fully-qualified URLs with scheme; malformed digests ("@sha256:xyz" truncated).

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/47e6fdc735649eb7. Report an issue: GitHub.