kubernetes/kops · error

different types for copy target %s

Error message

different types for copy target %s

What it means

Copy deduplicates file copy tasks by name (the target file path). If a task name already exists in the map but holds a *CopyImage instead of a *CopyFile (or vice versa), the target is being used for two different task kinds, so Copy aborts with this error.

Source

Thrown at pkg/assets/assetcopy/copy.go:72

			tasks[copyImageTask.Name] = copyImageTask
		}
	}

	for _, fileAsset := range fileAssets {
		if fileAsset.DownloadURL.String() != fileAsset.CanonicalURL.String() {
			copyFileTask := &CopyFile{
				Name:       fileAsset.CanonicalURL.String(),
				TargetFile: fileAsset.DownloadURL.String(),
				SourceFile: fileAsset.CanonicalURL.String(),
				SHA:        fileAsset.SHAValue.Hex(),
				VFSContext: vfsContext,
				Cluster:    cluster,
			}

			if existing, ok := tasks[copyFileTask.Name]; ok {
				e, ok := existing.(*CopyFile)
				if !ok {
					return fmt.Errorf("different types for copy target %s", copyFileTask.Name)
				}
				if e.TargetFile != copyFileTask.TargetFile {
					return fmt.Errorf("different targets for same file %s: %s vs %s", copyFileTask.Name, copyFileTask.TargetFile, e.TargetFile)
				}
				if e.SHA != copyFileTask.SHA {
					return fmt.Errorf("different sha for same file %s: %s vs %s", copyFileTask.Name, copyFileTask.SHA, e.SHA)
				}
			}

			tasks[copyFileTask.Name] = copyFileTask
		}
	}

	ch := make(chan error, 5)
	for i := 0; i < cap(ch); i++ {
		ch <- nil
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Make file and image targets occupy distinct namespaces/names so they never collide
  2. Fix the asset configuration that reuses one target name for both a file path and an image target
  3. Regenerate the asset list so each target is produced by exactly one task type
Defensive patterns

Strategy: validation

Validate before calling

names := map[string]string{}
for _, t := range allTasks {
	if prev, ok := names[t.Name()]; ok && prev != fmt.Sprintf("%T", t) {
		return fmt.Errorf("pre-check: target %s reused by %s and %s", t.Name(), prev, fmt.Sprintf("%T", t))
	}
	names[t.Name()] = fmt.Sprintf("%T", t)
}

Type guard

func targetIsFreeForFile(tasks map[string]Task, name string) bool {
	_, occupied := tasks[name]
	return !occupied
}

Try / catch

if err := copy.Run(ctx); err != nil {
	if strings.Contains(err.Error(), "different types for copy target") {
		return fmt.Errorf("asset config bug: %w — file and image targets must not share a name", err)
	}
	return err
}

Prevention

When it happens

Trigger: A file asset's target path equals an image asset's target name within one Copy run, so tasks[name] holds a *CopyImage when a *CopyFile is inserted (or the map contains a non-CopyFile value under that name).

Common situations: Misconfigured asset targets where a file destination path collides with an image tag/target string; generated asset lists where the same logical name is reused by different asset types across versions.

Related errors


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