kubernetes/kops · error

unable to locate asset %q

Error message

unable to locate asset %q

What it means

In KubectlBuilder.Build, nodeup resolves the kubectl binary as a cluster asset via b.Assets.Find(assetName, assetPath). After the lookup returns without error, a nil asset means the kubectl asset was not found in the compiled-in or on-disk asset list, so nodeup cannot create the kubectl file task on the node.

Source

Thrown at nodeup/pkg/model/kubectl.go:51

var _ fi.NodeupModelBuilder = &KubectlBuilder{}

// Build is responsible for managing the kubectl on the nodes
func (b *KubectlBuilder) Build(c *fi.NodeupModelBuilderContext) error {
	if !b.HasAPIServer {
		return nil
	}

	{
		// TODO: Extract to common function?
		assetName := "kubectl"
		assetPath := ""
		asset, err := b.Assets.Find(assetName, assetPath)
		if err != nil {
			return fmt.Errorf("error trying to locate asset %q: %v", assetName, err)
		}
		if asset == nil {
			return fmt.Errorf("unable to locate asset %q", assetName)
		}

		c.AddTask(&nodetasks.File{
			Path:     b.KubectlPath() + "/" + assetName,
			Contents: asset,
			Type:     nodetasks.FileType_File,
			Mode:     s("0755"),
		})
	}

	{
		name := nodetasks.PKIXName{
			CommonName:   "kubecfg",
			Organization: []string{rbac.SystemPrivilegedGroup},
		}
		kubeconfig := b.BuildIssuedKubeconfig("kubecfg", name, c)

		c.AddTask(&nodetasks.File{

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Verify the kubectl asset exists in the asset store / file mirror referenced by the cluster spec (correct base URL, correct arch suffix).
  2. Check the cluster's kubernetesVersion is a valid, downloadable version so the kubectl asset URL resolves.
  3. Re-run kops update/apply so the asset manifest is regenerated, then retry nodeup.
  4. If on an air-gapped install, re-upload the missing kubectl binary to the mirror and confirm permissions.

Example fix

// before (nodeup run against empty mirror)
kops update cluster ... --url=https://internal-mirror/broken
// after (asset uploaded / correct base URL)
kops update cluster ... --url=https://internal-mirror/latest
Defensive patterns

Strategy: validation

Validate before calling

// before running nodeup, confirm the kubectl asset is fetchable
u := fmt.Sprintf("%s/%s/bin/linux/amd64/kubectl", baseURL, k8sVersion)
resp, err := http.Head(u)
if err != nil || resp.StatusCode != http.StatusOK {
    return fmt.Errorf("kubectl asset missing at %s", u)
}

Prevention

When it happens

Trigger: Running nodeup on a node when the kubectl asset is absent from the cluster's Assets (e.g. assets produced from an asset registry that did not include kubectl, an incorrect kubernetesVersion, or a missing/isolated file:// mirror).

Common situations: Air-gapped clusters where the kubectl mirror path is wrong or the file was not uploaded; mismatched KOPS_BASE_URL / asset store contents; versions of kOps where the kubectl asset for the target arch was not built.

Related errors


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