GoogleContainerTools/skaffold · error
%s %q: %w
Error message
%s %q: %w
What it means
The ImagePush call itself failed — the daemon rejected or could not start the push (e.g. `denied`, `not found`, or connection error). Skaffold wraps it with the semantic error key sErrors.PushImageErr and the offending ref, so the message reads like `pushing image "ref": <daemon error>`.
Source
Thrown at pkg/skaffold/docker/image.go:441
}
// Push pushes an image reference to a registry. Returns the image digest.
func (l *localDaemon) Push(ctx context.Context, out io.Writer, ref string) (string, error) {
registryAuth, err := l.encodedRegistryAuth(ctx, DefaultAuthHelper, ref)
if err != nil {
return "", fmt.Errorf("getting auth config for %q: %w", ref, err)
}
// Quick check if the image was already pushed (ignore any error).
if alreadyPushed, digest, err := l.isAlreadyPushed(ctx, ref, registryAuth); alreadyPushed && err == nil {
return digest, nil
}
rc, err := l.apiClient.ImagePush(ctx, ref, client.ImagePushOptions{
RegistryAuth: registryAuth,
})
if err != nil {
return "", fmt.Errorf("%s %q: %w", sErrors.PushImageErr, ref, err)
}
defer rc.Close()
var digest string
auxCallback := func(msg jsonstream.Message) {
if msg.Aux == nil {
return
}
var result PushResult
if err := json.Unmarshal(*msg.Aux, &result); err != nil {
log.Entry(ctx).Debug("Unable to parse push output:", err)
return
}
digest = result.Digest
}
if err := streamDockerMessages(out, rc, auxCallback); err != nil {View on GitHub (pinned to a1189de023)
Solutions
- Read the wrapped daemon error — `denied` means fix auth/permissions, `not found` means fix the ref/repo
- Re-login to the registry (`docker login <registry>`) to refresh credentials
- Verify the image ref is valid and lowercase for registries that require it
- Check network/proxy/TLS access to the registry from the Docker host
- Confirm your account has push permission to the target repository
Example fix
// before image: MyOrg/MyApp:latest # uppercase rejected by Docker Hub // after image: myorg/myapp:latest
Defensive patterns
Strategy: retry
Validate before calling
if strings.ContainsAny(ref, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
return fmt.Errorf("image ref must be lowercase for most registries: %s", ref)
} Try / catch
digest, err := daemon.Push(ctx, out, ref)
if err != nil && strings.Contains(err.Error(), sErrors.PushImageErr) {
// inspect wrapped daemon error: denied -> re-auth; not found -> fix ref
if strings.Contains(err.Error(), "denied") {
// refresh credentials then retry once
}
return fmt.Errorf("push failed for %s: %w", ref, err)
} Prevention
- Use lowercase image names for Docker Hub and similar registries
- Confirm write permissions on the target repository before pushing
- Refresh cloud registry tokens on a schedule in CI
- Verify registry reachability (DNS/proxy/TLS) from the Docker host
When it happens
Trigger: l.apiClient.ImagePush(ctx, ref, opts) returns an error: the registry denied access (bad/expired credentials), the repository does not exist or lacks permissions, the ref is invalid, or the daemon cannot reach the registry (network/DNS/TLS).
Common situations: Pushing to a namespace without write permission; repository name case mismatch (Docker Hub requires lowercase); expired cloud registry tokens; corporate proxy blocking the registry; typo in the image ref.
Related errors
- %s %q: %w
- getting auth config: %w
- getting auth config for %q: %w
- pulling image from repository: %w
- retrieving image config: %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/6e8591e87eb8e65a.
Report an issue: GitHub.