Billionmail/BillionMail · error

imagemagick thumbnail failed: %w output: %s

Error message

imagemagick thumbnail failed: %w
output: %s

What it means

GenerateThumbnail shells out to ImageMagick's 'magick' CLI via exec.CommandContext to produce a video thumbnail, capturing combined stdout/stderr. When the command exits non-zero (or the binary cannot be found/executed), the underlying error is wrapped as 'imagemagick thumbnail failed: %w' with the full CLI output appended, so both the Go-level failure and ImageMagick's own diagnostics are preserved in one message.

Source

Thrown at core/internal/service/video_gen/thumbnail.go:65

		cfg.InputPath,
		"-resize", fmt.Sprintf("%dx%d!", w, h),
		"-quality", "90",
		cfg.OutputPath,
	}
}

// GenerateThumbnail creates a thumbnail from a screenshot using ImageMagick.
// Requires: magick (ImageMagick) installed.
func GenerateThumbnail(ctx context.Context, cfg ThumbnailConfig) (string, error) {
	if err := os.MkdirAll(filepath.Dir(cfg.OutputPath), 0755); err != nil {
		return "", fmt.Errorf("create thumbnail dir: %w", err)
	}

	args := BuildThumbnailArgs(cfg)
	cmd := exec.CommandContext(ctx, "magick", args...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("imagemagick thumbnail failed: %w\noutput: %s", err, string(out))
	}

	return cfg.OutputPath, nil
}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Install ImageMagick (apt-get install imagemagick / apk add imagemagick) and confirm 'magick -version' works inside the container
  2. Run the exact args from BuildThumbnailArgs(cfg) by hand to inspect ImageMagick's output printed after 'output:' in the error
  3. Verify the input video path exists and is readable before calling GenerateThumbnail
  4. If running ImageMagick 6, either upgrade to IM7 or adapt BuildThumbnailArgs to invoke 'convert'
  5. Check context cancellation: if the pipeline is being shut down, the wrapped error will be context.Canceled

Example fix

// before
cmd := exec.CommandContext(ctx, "magick", args...)
out, err := cmd.CombinedOutput()
// after
if _, err := exec.LookPath("magick"); err != nil {
    return "", fmt.Errorf("imagemagick not found on PATH: %w", err)
}
cmd := exec.CommandContext(ctx, "magick", args...)
out, err := cmd.CombinedOutput()
Defensive patterns

Strategy: validation

Validate before calling

if _, err := exec.LookPath("magick"); err != nil {
    return fmt.Errorf("thumbnail prerequisite missing: install imagemagick: %w", err)
}
if info, err := os.Stat(inputVideoPath); err != nil || info.IsDir() {
    return fmt.Errorf("input video not readable: %s", inputVideoPath)
}
if ctx.Err() != nil {
    return ctx.Err()
}

Try / catch

urls, err := GenerateThumbnail(ctx, cfg)
if err != nil {
    var execErr *exec.ExitError
    switch {
    case errors.Is(err, context.Canceled):
        // pipeline shutdown; do not retry
    case errors.As(err, &execErr):
        log.Errorf("magick failed: %v", err) // output is embedded in the message
    default:
        log.Errorf("thumbnail error: %v", err)
    }
}

Prevention

When it happens

Trigger: magick is not installed or not on PATH (exec.ErrNotFound via CombinedOutput); the input video path does not exist or is unreadable (as tested by TestGenerateThumbnail_NonexistentInput); the supplied thumbnail args are malformed; or the context is cancelled before magick finishes (TestGenerateThumbnail_CancelledContext), causing Wait to fail with a context/deadline error.

Common situations: Minimal Docker images without imagemagick installed; ImageMagick 6 environments that ship the binary as 'convert' instead of 'magick'; video files in formats magick cannot delegate to ffmpeg; missing file permissions; pipeline shutdown cancelling the context mid-conversion.

Related errors


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