Billionmail/BillionMail · error
imagemagick annotate failed: %w\noutput: %s
Error message
imagemagick annotate failed: %w\noutput: %s
What it means
Annotate shells out to ImageMagick's `magick` CLI to draw annotations onto an image. If the command exits non-zero, it wraps the exec error together with the combined stdout/stderr so the caller can see why ImageMagick failed. It is thrown for any magick invocation failure: missing binary, unreadable input, bad arguments, or ImageMagick processing errors.
Source
Thrown at core/internal/service/video_gen/annotate.go:101
Type: AnnotationText,
X: 100, Y: 950,
Text: "High ad spend but room for improvement",
Color: "#FF6600",
})
}
return anns
}
return nil
}
// Annotate applies visual annotations to a screenshot using ImageMagick.
// Requires: convert (ImageMagick) installed.
func Annotate(ctx context.Context, cfg AnnotateConfig) error {
args := BuildAnnotateArgs(cfg)
cmd := exec.CommandContext(ctx, "magick", args...)
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("imagemagick annotate failed: %w\noutput: %s", err, string(out))
}
return nil
}
// BuildAnnotateArgs constructs the ImageMagick CLI arguments for the given config.
// Exported for testing without requiring ImageMagick installed.
func BuildAnnotateArgs(cfg AnnotateConfig) []string {
args := []string{cfg.InputPath}
for _, ann := range cfg.Annotations {
color := ann.Color
if color == "" {
color = "red"
}
switch ann.Type {
case AnnotationCircle:
// Draw a circle outlineView on GitHub (pinned to fc36c76c05)
Solutions
- Install ImageMagick 7 (which provides `magick`) and ensure it is on PATH: apt-get install imagemagick (v7) or imagemagick7
- Check the `output:` portion of the error for the specific magick CLI complaint
- Verify the input file exists and is readable, and the output directory is writable
- Run the BuildAnnotateArgs output manually to reproduce: magick <args...>
- If the error is 'signal: killed' or context deadline, increase the timeout or image size limits
Example fix
// before (CI Dockerfile) FROM golang:1.22 // after FROM golang:1.22 RUN apt-get update && apt-get install -y imagemagick && rm -rf /var/lib/apt/lists/*
Defensive patterns
Strategy: try-catch
Validate before calling
func magickAvailable() error {
path, err := exec.LookPath("magick")
if err != nil { return fmt.Errorf("ImageMagick v7 'magick' not on PATH: %w", err) }
return nil
}
// also pre-check: file exists
if _, err := os.Stat(cfg.InputPath); err != nil { return err } Try / catch
if err := video_gen.Annotate(ctx, cfg); err != nil {
var ee *exec.ExitError
if errors.As(err, &ee) {
log.Printf("magick failed (exit %d): %s", ee.ExitCode(), err)
return fmt.Errorf("install ImageMagick or fix args: %w", err)
}
return err
} Prevention
- Install ImageMagick 7 in every environment running video_gen (add to Dockerfile)
- Pre-flight exec.LookPath("magick") at service startup
- Verify input/output paths exist and are writable before calling Annotate
- Keep annotation configs validated (BuildAnnotateArgs is exported for testing)
When it happens
Trigger: exec.CommandContext(ctx, "magick", args...) returns a non-nil error — magick not installed/not on PATH, input file missing or unreadable, invalid annotate arguments, disk full, or context cancelled before completion.
Common situations: ImageMagick not installed in the container/host (video_gen requires it); typo'd image path; policy.xml restricting operations; arguments producing an option error visible in `output`; context deadline exceeded on large images.
Related errors
- annotate %s: %w
- imagemagick thumbnail failed: %w output: %s
- ffmpeg compositing failed: %w\noutput: %s
- rar compression failed: %s - %s
- rar file was not created successfully
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/7233075c5b7b32e3.
Report an issue: GitHub.