{"record":{"id":"067c98cd000f81bc","repo":"goreleaser/goreleaser","slug":"could-not-copy-q-to-q-w","errorCode":null,"errorMessage":"could not copy %q to %q: %w","messagePattern":"could not copy %q to %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pipe/ko/ko.go","lineNumber":584,"sourceCode":"\tif path == \"\" {\n\t\treturn nil\n\t}\n\tif matched, _ := regexp.MatchString(`^\\.?(\\.\\/[^\\/]?.*)?$`, path); !matched {\n\t\treturn errInvalidMainPath\n\t}\n\t// 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\n\tif strings.HasSuffix(path, \".go\") {\n\t\treturn errInvalidMainGoPath\n\t}\n\treturn nil\n}\n\nfunc copyImage(src, dst string) (string, error) {\n\tlog.WithField(\"src\", src).\n\t\tWithField(\"dst\", dst).\n\t\tInfo(\"copying manifest\")\n\tif err := crane.Copy(src, dst, crane.WithAuthFromKeychain(keychain)); err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not copy %q to %q: %w\", src, dst, err)\n\t}\n\tdigest, err := crane.Digest(dst, crane.WithAuthFromKeychain(keychain))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not get digest of %q: %w\", dst, err)\n\t}\n\treturn digest, nil\n}\n\nfunc makeArtifact(id, name, digest string) *artifact.Artifact {\n\tart := &artifact.Artifact{\n\t\tType:  artifact.DockerManifest,\n\t\tName:  name,\n\t\tPath:  name,\n\t\tExtra: map[string]any{},\n\t}\n\tif id != \"\" {\n\t\tart.Extra[artifact.ExtraID] = id\n\t}","sourceCodeStart":566,"sourceCodeEnd":602,"githubUrl":"https://github.com/goreleaser/goreleaser/blob/f5edd7395693c0c6b501dc722d445d2e86af854d/internal/pipe/ko/ko.go#L566-L602","documentation":"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.","triggerScenarios":"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.","commonSituations":"Second repo on a different registry with different credentials; typo in destination repo name; rate limits or quota on the target registry.","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"],"exampleFix":"// before\nko:\n  repositories:\n    - ghcr.io/owner/app\n    - quay.io/wrong/app\n// after\nko:\n  repositories:\n    - ghcr.io/owner/app\n    - quay.io/owner/app","handlingStrategy":"retry","validationCode":"for r in $(yq '.kos[].repositories[]' .goreleaser.yaml); do docker login \"$(echo $r | cut -d/ -f1)\" -u \"$USER\" -p \"$TOKEN\"; done","typeGuard":null,"tryCatchPattern":"if err := doRelease(); err != nil {\n    var cErr copyError\n    if errors.As(err, &cErr) && isNetworkErr(err) {\n        return retry(3, doRelease)\n    }\n    return err\n}","preventionTips":["Authenticate to every registry listed in ko.repositories","Pre-create all destination repositories","Limit to registries with similar permissions/policies"],"tags":["ko","docker","registry","crane","network"],"backgroundTag":"registry-push-failed","analyzedSha":"f5edd7395693c0c6b501dc722d445d2e86af854d","analyzedAt":"2026-09-05T09:57:18.807Z","contentChangedAt":"2026-09-05T09:57:18.807Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}