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

  1. Read the wrapped daemon error — `denied` means fix auth/permissions, `not found` means fix the ref/repo
  2. Re-login to the registry (`docker login <registry>`) to refresh credentials
  3. Verify the image ref is valid and lowercase for registries that require it
  4. Check network/proxy/TLS access to the registry from the Docker host
  5. 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

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


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/6e8591e87eb8e65a. Report an issue: GitHub.