goreleaser/goreleaser · error
could not copy %q to %q: %w
Error message
could not copy %q to %q: %w
What it means
When multiple image repositories are configured (and not in snapshot mode), the image published to imageRepos[0] is copied to each additional repo via crane.Copy; failure is wrapped as "could not copy %q to %q". The source image exists but the copy/push to the destination failed.
Source
Thrown at internal/pipe/ko/ko.go:584
if path == "" {
return nil
}
if matched, _ := regexp.MatchString(`^\.?(\.\/[^\/]?.*)?$`, path); !matched {
return errInvalidMainPath
}
// paths sure can have dots in them, but if the path ends in .go, it's probably a file that one misundertood as a valid value
if strings.HasSuffix(path, ".go") {
return errInvalidMainGoPath
}
return nil
}
func copyImage(src, dst string) (string, error) {
log.WithField("src", src).
WithField("dst", dst).
Info("copying manifest")
if err := crane.Copy(src, dst, crane.WithAuthFromKeychain(keychain)); err != nil {
return "", fmt.Errorf("could not copy %q to %q: %w", src, dst, err)
}
digest, err := crane.Digest(dst, crane.WithAuthFromKeychain(keychain))
if err != nil {
return "", fmt.Errorf("could not get digest of %q: %w", dst, err)
}
return digest, nil
}
func makeArtifact(id, name, digest string) *artifact.Artifact {
art := &artifact.Artifact{
Type: artifact.DockerManifest,
Name: name,
Path: name,
Extra: map[string]any{},
}
if id != "" {
art.Extra[artifact.ExtraID] = id
}View on GitHub (pinned to f5edd73956)
Solutions
- Read src/dst in the message and test `crane copy <src> <dst>` manually
- Authenticate to the additional registry (its keychain/credential helper entry)
- Create the destination repository or grant create permission
- Verify the destination repo name spelling and registry host
Example fix
// before
ko:
repositories:
- ghcr.io/owner/app
- quay.io/wrong/app
// after
ko:
repositories:
- ghcr.io/owner/app
- quay.io/owner/app Defensive patterns
Strategy: retry
Validate before calling
for r in $(yq '.kos[].repositories[]' .goreleaser.yaml); do docker login "$(echo $r | cut -d/ -f1)" -u "$USER" -p "$TOKEN"; done
Try / catch
if err := doRelease(); err != nil {
var cErr copyError
if errors.As(err, &cErr) && isNetworkErr(err) {
return retry(3, doRelease)
}
return err
} Prevention
- Authenticate to every registry listed in ko.repositories
- Pre-create all destination repositories
- Limit to registries with similar permissions/policies
When it happens
Trigger: crane.Copy(src, dst, keychain auth) fails: destination repo doesn't exist / no create permission, auth missing for the additional registry, network failure, or unsupported destination.
Common situations: Second repo on a different registry with different credentials; typo in destination repo name; rate limits or quota on the target registry.
Related errors
- publish: %w
- could not get digest of %q: %w
- failed to push %s: %w
- docker buildx imagetools inspect %s: %w
- newPublisher: %w
AI-assisted analysis of goreleaser/goreleaser@f5edd73956 (2026-09-05).
Data as JSON: /api/errors/067c98cd000f81bc.
Report an issue: GitHub.