vxcontrol/pentagi · error

image download stream processing failed: %w

Error message

image download stream processing failed: %w

What it means

Returned when the ImagePull API call succeeded but draining the pull progress stream (io.Copy to io.Discard) failed mid-transfer. This indicates the pull was interrupted — the stream from the daemon broke before the pull finished.

Source

Thrown at backend/pkg/docker/client.go:1195

	if err != nil {
		return fmt.Errorf("failed to list images: %w", err)
	}

	if imageExistsLocally := len(images.Items) > 0; imageExistsLocally {
		return nil
	}

	dc.logger.WithContext(ctx).WithField("image", imageName).Info("initiating image download from registry...")

	pullStream, err := dc.client.ImagePull(ctx, imageName, client.ImagePullOptions{})
	if err != nil {
		return fmt.Errorf("failed to pull image: %w", err)
	}
	defer pullStream.Close()

	// drain pull stream to completion
	if _, err := io.Copy(io.Discard, pullStream); err != nil {
		return fmt.Errorf("image download stream processing failed: %w", err)
	}

	dc.logger.WithContext(ctx).WithField("image", imageName).Debug("image pull completed")

	return nil
}

func getHostDockerSocket(ctx context.Context, cli *client.Client) string {
	daemonHost := strings.TrimPrefix(cli.DaemonHost(), "unix://")
	if info, err := os.Stat(daemonHost); err != nil || info.IsDir() {
		return defaultDockerSocketPath
	}

	hostname, err := os.Hostname()
	if err != nil {
		return daemonHost
	}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Increase the context timeout or remove the deadline for large image pulls
  2. Retry the pull — completed layers are cached and resume is cheap
  3. Check daemon logs and host network stability for mid-stream disconnects
  4. Check whether the caller cancels the ctx unexpectedly
  5. Pull the image manually on the host to warm the cache before running the flow

Example fix

// before
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
// after
ctx, cancel := context.WithTimeout(ctx, 10*time.Minute) // allow large image pulls
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

func isPullStreamError(err error) bool { return strings.Contains(err.Error(), "image download stream processing failed") }

Try / catch

err := dc.pullImage(ctx, imageName)
if err != nil && strings.Contains(err.Error(), "image download stream processing failed") {
    // layers are cached; a retry resumes cheaply
    err = retry.Do(func() error { return dc.pullImage(ctx, imageName) }, retry.Attempts(3))
}

Prevention

When it happens

Trigger: io.Copy on the pull stream returns an error: connection to the Docker daemon dropped mid-pull, context deadline/cancellation fires while the pull is in progress, or the daemon closes the stream abnormally.

Common situations: Slow/unstable network pulling large images combined with a short context timeout; caller cancels the context; daemon restart during a long pull; proxy terminating long-lived connections.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/197f6e1940fcdf83. Report an issue: GitHub.