GoogleContainerTools/skaffold · error

reading image %q: %w

Error message

reading image %q: %w

What it means

Push loads the local image tarball with tarball.ImageFromPath and returns "reading image %q" when the file cannot be read or parsed as a Docker/OCI image archive. The wrapped error distinguishes filesystem problems (missing file, permissions) from format problems (invalid tar, no manifest.json).

Source

Thrown at pkg/skaffold/docker/remote.go:110

func RetrieveRemoteConfig(identifier string, cfg Config, platform v1.Platform) (*v1.ConfigFile, error) {
	img, err := getRemoteImage(identifier, cfg, platform)
	if err != nil {
		return nil, err
	}

	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()) {

View on GitHub (pinned to a1189de023)

Solutions

  1. Verify the tarball exists and is non-empty: `ls -la <tarPath>`; if missing, fix the build step that produces it.
  2. Check it's a docker-save archive: `tar -tf img.tar | grep manifest.json` — if absent, regenerate with `docker save -o img.tar <image>`.
  3. If the source is an OCI layout, convert it first (e.g. `skopeo copy oci:dir docker-archive:img.tar`).
  4. Confirm the file path passed is the file itself, not the containing directory.
  5. Re-run the image build/save to rule out a truncated or corrupted archive.

Example fix

// before
os.IsDir check missing; digest, err := docker.Push("out/image", tag, cfg, nil)
// after
if fi, err := os.Stat("out/image.tar"); err != nil || fi.IsDir() { return fmt.Errorf("image tarball missing: out/image.tar") }
digest, err := docker.Push("out/image.tar", tag, cfg, nil)
Defensive patterns

Strategy: validation

Validate before calling

func validateImageTar(path string) error {
	fi, err := os.Stat(path)
	if err != nil { return fmt.Errorf("tarball missing: %w", err) }
	if fi.IsDir() || fi.Size() == 0 { return fmt.Errorf("%s is not a non-empty file", path) }
	f, err := os.Open(path)
	if err != nil { return err }
	defer f.Close()
	tr := tar.NewReader(f)
	for {
		h, err := tr.Next()
		if err == io.EOF { return errors.New("no manifest.json in archive") }
		if err != nil { return err }
		if h.Name == "manifest.json" { return nil }
	}
}

Type guard

func isDockerSaveTar(path string) bool { return validateImageTar(path) == nil }

Try / catch

if err := validateImageTar(tarPath); err != nil { return err }
if _, err := docker.Push(tarPath, tag, cfg, platforms); err != nil {
	if strings.Contains(err.Error(), "reading image") {
		return fmt.Errorf("%s is not a valid docker-save archive; regenerate with `docker save -o %s <image>`", tarPath, tarPath)
	}
	return err
}

Prevention

When it happens

Trigger: tarPath points to a nonexistent file or wrong path; the file is not a `docker save` archive (e.g. it's a single-layer tar, an OCI layout dir, or compressed); the archive's manifest.json is missing or corrupted.

Common situations: Build step silently failed so the .tar was never produced; passing a directory instead of a tar; passing a docker buildx output in OCI layout format where tarball.ImageFromPath expects docker-save format; partial download/truncated file.

Related errors


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