kubernetes/kops · error

unable to remap a nil URL

Error message

unable to remap a nil URL

What it means

AssetBuilder.RemapFile rejects a nil canonical URL argument before doing any work. Callers must pass a parsed *url.URL for the file they want remapped; a nil indicates the caller failed to construct the URL (e.g. url.Parse failed earlier or was skipped).

Source

Thrown at pkg/assets/builder.go:322

		return image
	}

	digest, err := imageDigestResolver(image)
	if err != nil {
		klog.Warningf("failed to digest image %q: %s", image, err)
		return image
	}

	return image + "@" + digest
}

// RemapFile returns a remapped URL for the file, if AssetsLocation is defined.
// It is returns in a FileAsset, alongside the SHA hash of the file.
// The SHA hash is is knownHash is provided, and otherwise will be found first by
// checking the canonical URL against our well-known hashes, and failing that via download.
func (a *AssetBuilder) RemapFile(canonicalURL *url.URL, knownHash *hashing.Hash) (*FileAsset, error) {
	if canonicalURL == nil {
		return nil, fmt.Errorf("unable to remap a nil URL")
	}

	fileAsset := &FileAsset{
		DownloadURL:  canonicalURL,
		CanonicalURL: canonicalURL,
	}

	if a.assetsLocation != nil && a.assetsLocation.FileRepository != nil {
		normalizedFile, err := a.remapURL(canonicalURL)
		if err != nil {
			return nil, err
		}

		if canonicalURL.Host != normalizedFile.Host {
			fileAsset.DownloadURL = normalizedFile
			klog.V(4).Infof("adding remapped file: %q", fileAsset.DownloadURL.String())
		}
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure the caller always parses and passes a valid *url.URL; check the option/env that supplies the base URL.
  2. Add an early check at the call site and return a clearer error naming the missing setting.
  3. For nodeup/kops config, verify KubernetesVersion and file URLs are fully specified.

Example fix

// before
u, err := url.Parse(fileURL) // fileURL == "" -> treated as ok
fileAsset, err := a.RemapFile(u, hash)
// after
if fileURL == "" {
	return nil, fmt.Errorf("file url is not defined")
}
u, err := url.Parse(fileURL)
if err != nil {
	return nil, err
}
fileAsset, err := a.RemapFile(u, hash)
Defensive patterns

Strategy: validation

Validate before calling

if canonicalURL == nil {
	return fmt.Errorf("file URL is not configured; check kubernetes/cni download URL settings")
}

Type guard

func isValidURL(u *url.URL) bool { return u != nil && u.Scheme != "" && u.Host != "" }

Try / catch

fileAsset, err := assetBuilder.RemapFile(canonicalURL, knownHash)
if err != nil {
	if strings.Contains(err.Error(), "unable to remap a nil URL") {
		return fmt.Errorf("caller bug: canonical URL for %s was nil; check base URL config", name)
	}
	return err
}

Prevention

When it happens

Trigger: Passing nil as canonicalURL to RemapFile — typically when a values source produced an empty/missing base URL and the caller skipped url.Parse instead of failing early.

Common situations: Config where the kubernetes download URL or CNI URL env/option is empty, so the code composes a nil URL; a version string lookup returning empty causing url.Parse of "" that callers treated as ok.

Related errors


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