GoogleContainerTools/skaffold · error
%s %q: %w
Error message
%s %q: %w
What it means
Push fails with "<PushImageErr> %q" (sErrors.PushImageErr, typically "pushing image") when remote.Write cannot upload the loaded tarball image to the target registry. This wraps go-containerregistry's remote.Write error — auth failures, TLS problems, connectivity, blob upload errors, or registry denial (quota, permissions).
Source
Thrown at pkg/skaffold/docker/remote.go:114
}
return img.ConfigFile()
}
// Push pushes the tarball image
func Push(tarPath, tag string, cfg Config, platforms []specs.Platform) (string, error) {
t, err := name.NewTag(tag, name.WeakValidation)
if err != nil {
return "", fmt.Errorf("parsing tag %q: %w", tag, err)
}
i, err := tarball.ImageFromPath(tarPath, nil)
if err != nil {
return "", fmt.Errorf("reading image %q: %w", tarPath, err)
}
if err := remote.Write(t, i, remote.WithAuthFromKeychain(primaryKeychain)); err != nil {
return "", fmt.Errorf("%s %q: %w", sErrors.PushImageErr, t, err)
}
return getRemoteDigest(tag, cfg, platforms)
}
func getRemoteImage(identifier string, cfg Config, platform v1.Platform) (v1.Image, error) {
ref, err := parseReference(identifier, cfg)
if err != nil {
return nil, err
}
options := []remote.Option{
remote.WithAuthFromKeychain(primaryKeychain),
}
if IsInsecure(ref, cfg.GetInsecureRegistries()) {
options = append(options, insecureTransportOption())
}
if platform.String() != "" {
options = append(options, remote.WithPlatform(platform))View on GitHub (pinned to a1189de023)
Solutions
- Authenticate: `docker login <registry>` (or configure the proper credential helper for gcloud/aws/ecr) and retry.
- Read the wrapped error — a 401/403 indicates credentials/permissions; DENIED indicates repo policy; timeout indicates network/proxy.
- Verify push permission on the target repository/project (IAM, or repo-level ACLs in Harbor/Quay).
- If the registry is HTTP or has a self-signed cert, add it to insecure_registries in the Skaffold config.
- Check registry-side limits (quota, rate limits, image size) and egress/proxy settings.
Example fix
// before docker.Push(tarPath, "us.gcr.io/proj/app:v1", cfg, nil) // 403 DENIED // after # grant push access / login first # gcloud auth activate-service-account --key-file=sa.json # gcloud auth configure-docker us.gcr.io docker.Push(tarPath, "us.gcr.io/proj/app:v1", cfg, nil)
Defensive patterns
Strategy: try-catch
Validate before calling
func canPush(ref string) error {
repo, err := name.NewRepository(ref, name.WeakValidation)
if err != nil { return err }
_, err = remote.Index(repo, remote.WithAuthFromKeychain(defaultKeychain())) // auth smoke test
if err != nil {
var te *transport.Error
if errors.As(err, &te) && (te.StatusCode == 401 || te.StatusCode == 403) {
return fmt.Errorf("no push credentials/permissions for %s", ref)
}
}
return nil
} Type guard
func hasRegistryAuth(registry string) bool {
cfg, err := config.Load()
if err != nil { return false }
auth, err := cfg.GetAuth(registry)
return err == nil && auth != authn.Anonymous
} Try / catch
if _, err := docker.Push(tarPath, tag, cfg, platforms); err != nil {
var te *transport.Error
if errors.As(err, &te) {
switch te.StatusCode {
case 401, 403: return fmt.Errorf("run `docker login %s` and verify push permissions", registryOf(tag))
case http.StatusGatewayTimeout: return fmt.Errorf("registry timeout; check network/proxy")
}
}
return err
} Prevention
- Script docker login (or cloud credential-helper config) before any push in CI.
- Verify repository IAM/ACL push rights for the identity in use.
- Add self-signed/HTTP registries to insecure_registries ahead of time.
- Inspect the wrapped transport error status to choose auth vs network remediation.
When it happens
Trigger: remote.Write to the parsed tag fails: unauthenticated/unauthorized (401/403), registry unreachable, insecure registry without skip-verify configured, image exceeds repo size limits, or tag already protected.
Common situations: docker login never run for the registry or token expired; GCR/Artifact Registry permissions missing on the service account; corporate proxy blocking the upload; pushing to a read-only mirror.
Related errors
- getting auth config: %w
- %s %q: %w
- pulling image from repository: %w
- getting image: %w
- INIT_DOCKER_NETWORK_CONTAINER_DOES_NOT_EXIST
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/3845a17cd1f1c5ac.
Report an issue: GitHub.