kubernetes/kops · error

unable to parse CNI plugin binaries asset URL %q: %v

Error message

unable to parse CNI plugin binaries asset URL %q: %v

What it means

FindCNIAssets resolves the CNI plugin binaries tarball URL for a cluster's instance groups. When both CNI_VERSION_URL and CNI_ASSET_HASH_STRING env vars are set, it overrides the built-in defaults and parses the URL with net/url.Parse before remapping the asset. This error wraps a failure of url.Parse: the CNI_VERSION_URL value is not a valid URL (e.g. no scheme, control characters, or malformed).

Source

Thrown at pkg/nodemodel/wellknownassets/cni.go:65

	defaultCNIAssetArm64K8s_36 = "https://github.com/containernetworking/plugins/releases/download/v1.9.1/cni-plugins-linux-arm64-v1.9.1.tgz"

	// Environment variable for overriding CNI url
	ENV_VAR_CNI_ASSET_URL  = "CNI_VERSION_URL"
	ENV_VAR_CNI_ASSET_HASH = "CNI_ASSET_HASH_STRING"
)

func FindCNIAssets(ig model.InstanceGroup, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
	// Override CNI packages from env vars
	cniAssetURL := os.Getenv(ENV_VAR_CNI_ASSET_URL)
	cniAssetHash := os.Getenv(ENV_VAR_CNI_ASSET_HASH)

	if cniAssetURL != "" && cniAssetHash != "" {
		klog.V(2).Infof("Using CNI asset URL %q, as set in %s", cniAssetURL, ENV_VAR_CNI_ASSET_URL)
		klog.V(2).Infof("Using CNI asset hash %q, as set in %s", cniAssetHash, ENV_VAR_CNI_ASSET_HASH)

		u, err := url.Parse(cniAssetURL)
		if err != nil {
			return nil, fmt.Errorf("unable to parse CNI plugin binaries asset URL %q: %v", cniAssetURL, err)
		}

		h, err := hashing.FromString(cniAssetHash)
		if err != nil {
			return nil, fmt.Errorf("unable to parse CNI plugin binaries asset hash %q: %v", cniAssetHash, err)
		}

		asset, err := assetBuilder.RemapFile(u, h)
		if err != nil {
			return nil, fmt.Errorf("unable to remap CNI plugin binaries asset: %v", err)
		}

		return asset, nil
	}

	switch arch {
	case architectures.ArchitectureAmd64:
		switch {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Print `echo $CNI_VERSION_URL` and fix it to a full absolute URL, e.g. https://github.com/containernetworking/plugins/releases/download/v1.6.2/cni-plugins-linux-amd64-v1.6.2.tgz
  2. If you don't intend to override the CNI asset, unset CNI_VERSION_URL (and CNI_ASSET_HASH_STRING) so kOps uses its built-in defaults
  3. Validate the URL with `url.Parse` or `python3 -c 'import urllib.parse; urllib.parse.urlparse(...)'` before exporting it in scripts/CI
  4. Check quoting in shell/Makefile definitions so interpolation doesn't produce a malformed value

Example fix

// before
export CNI_VERSION_URL="containernetworking/plugins/releases/download/v1.6.2/cni-plugins-linux-amd64-v1.6.2.tgz"
// after
export CNI_VERSION_URL="https://github.com/containernetworking/plugins/releases/download/v1.6.2/cni-plugins-linux-amd64-v1.6.2.tgz"
Defensive patterns

Strategy: validation

Validate before calling

u := os.Getenv("CNI_VERSION_URL")
if u != "" {
    if _, err := url.Parse(u); err != nil {
        return fmt.Errorf("invalid %s: %w", "CNI_VERSION_URL", err)
    }
}

Type guard

func isValidURL(s string) bool {
    u, err := url.Parse(s)
    return err == nil && u.Scheme != "" && u.Host != ""
}

Try / catch

if _, err := FindCNIAssets(ig, assetBuilder, arch); err != nil {
    if strings.Contains(err.Error(), "unable to parse CNI plugin binaries asset URL") {
        klog.Errorf("check CNI_VERSION_URL env var: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: FindCNIAssets (via BuildKubernetesFileAssets) is called while os.Getenv("CNI_VERSION_URL") and os.Getenv("CNI_ASSET_HASH_STRING") are both non-empty, and url.Parse(cniAssetURL) returns a non-nil error.

Common situations: CNI_VERSION_URL set to a value without a scheme (e.g. "containernetworking/plugins/download/x.tgz"), a typo'd or truncated URL, a shell-interpolated variable that expanded to garbage, or a URL containing spaces/illegal characters from a CI config or Makefile.

Understand the failure class

Related errors


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