Billionmail/BillionMail · error

failed to pull image: %w

Error message

failed to pull image: %w

What it means

ExecHostCommand needs an alpine image to launch its host-command container. It first inspects the image locally; if absent it calls ImagePull. Any failure pulling from the registry (auth, network, tag missing) aborts the host command with this wrapped error.

Source

Thrown at core/internal/service/dockerapi/dockerapi.go:280

	result := &HostCommandResult{
		ExitCode: -1,
	}

	// Check if docker.sock is mounted
	if _, err := os.Stat("/var/run/docker.sock"); os.IsNotExist(err) {
		return nil, fmt.Errorf("docker.sock not mounted, cannot access Docker API")
	}

	// Specify the base image to use
	baseImage := "alpine:latest"

	// Check if the image exists, pull it if it doesn't
	_, err := d.client.ImageInspect(ctx, baseImage)
	if err != nil {
		// Image doesn't exist, try to pull it
		reader, err := d.client.ImagePull(ctx, baseImage, image.PullOptions{})
		if err != nil {
			return nil, fmt.Errorf("failed to pull image: %w", err)
		}
		defer reader.Close()

		// Wait for the image pull to complete
		_, _ = io.Copy(io.Discard, reader)
	}

	// Create temporary container configuration
	config := &container.Config{
		Image:      baseImage,
		Cmd:        command,
		WorkingDir: "/host_root", // Set working directory to mount point
		Tty:        false,
		Entrypoint: []string{},
	}

	// Use privileged mode and mount the host's root directory
	hostConfig := &container.HostConfig{

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Pre-pull the image once: `docker pull alpine:latest` so ImageInspect succeeds and the pull path is skipped
  2. Restore network/DNS from the host to the registry, or configure a reachable registry mirror in daemon.json
  3. docker login to the required registry if pulls are authenticated/rate-limited
  4. Pin a cached specific tag (e.g. alpine:3.20) instead of latest to reduce pull dependency

Example fix

// before
# runtime pulls on demand, fails offline
// after (deploy step)
docker pull alpine:latest && ./app  # image cached locally
Defensive patterns

Strategy: fallback

Validate before calling

if _, err := d.client.ImageInspect(ctx, "alpine:latest"); err != nil {
    if err := prePull(ctx, d.client, "alpine:latest"); err != nil {
        return fmt.Errorf("image unavailable offline: %w", err)
    }
}

Try / catch

res, err := api.ExecHostCommand(ctx, cmd)
if err != nil && strings.Contains(err.Error(), "failed to pull image") {
    log.Warnf("registry pull failed: %v — retrying or using cached tag", err)
    return runWithFallbackImage(ctx, "alpine:3.20", cmd)
}

Prevention

When it happens

Trigger: alpine:latest not present locally AND ImagePull fails — no internet/DNS, registry rate-limited (Docker Hub 429), private mirror requires credentials, or image name/tag unavailable.

Common situations: Air-gapped or restricted-network deployments; Docker Hub pull throttling after repeated anonymous pulls; registry outage; IPv6/DNS problems in the container runtime.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/88c11bd872e25e7c. Report an issue: GitHub.