Billionmail/BillionMail · error
annotate
Error message
annotate %s: %w
What it means
AnnotateAll iterates over scene types, calling Annotate for each. If any single annotation pass fails, the whole batch aborts and the error is wrapped with the scene type so you know which image failed. It is a pass-through wrapper — the root cause is always in the inner 'imagemagick annotate failed' error.
Solutions
- Read the wrapped cause: the scene type in this message plus the 'output:' text from the inner error
- Check that the input screenshot and output path for that specific scene type exist and are writable
- Run the failing scene's magick command manually to isolate the bad argument
- Ensure ImageMagick is installed in the environment running AnnotateAll
- Add pre-flight validation of scene configs/paths before starting the batch
Example fix
// before
if _, err := os.Stat(p.input); err != nil { /* proceeds anyway */ }
// after
if _, err := os.Stat(p.input); err != nil {
return nil, fmt.Errorf("scene %s input missing: %w", p.typ, err)
} Defensive patterns
Strategy: validation
Validate before calling
for _, p := range scenes {
if _, err := os.Stat(p.input); err != nil {
return nil, fmt.Errorf("scene %s: input missing: %w", p.typ, err)
}
}
if err := exec.Command("magick", "-version").Run(); err != nil {
return nil, errors.New("magick not available for annotate batch")
} Try / catch
annotated, err := video_gen.AnnotateAll(ctx, scenes)
if err != nil {
var sceneErr error
if strings.HasPrefix(err.Error(), "annotate ") {
sceneErr = errors.Unwrap(err) // inspect the magick failure for the specific scene
}
return fmt.Errorf("annotate batch aborted: %w (cause: %v)", err, sceneErr)
} Prevention
- Run the screenshot step's success/failure for every scene before annotating
- Pre-validate all scene input/output paths in one pass before starting the batch
- Ensure ImageMagick is installed wherever AnnotateAll runs
- Consider continuing per-scene and collecting errors instead of failing the whole batch
When it happens
Trigger: Annotate returns an error for a scene with type p.typ — magick missing, bad input/output path for that scene, or invalid annotation config for that scene type.
Common situations: One scene's screenshot file missing while others succeed; per-scene annotation text/config invalid; ImageMagick installed for some runners but not others; running during pipeline where a prior screenshot step silently failed.
Related errors
- imagemagick annotate failed
- imagemagick thumbnail failed
- contact missing website_url
- create thumbnail dir
- Failed to generate DKIM key pair
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/721b87c0531ef2e1.
Report an issue: GitHub.
Appendix: source
Thrown at core/internal/service/video_gen/annotate.go:215
output string
}{
{ScreenshotHomepage, result.Homepage, annotated.Homepage},
{ScreenshotContact, result.Contact, annotated.Contact},
{ScreenshotGoogle, result.Google, annotated.Google},
}
for _, p := range pairs {
anns := DefaultAnnotations(p.typ, signals)
if len(anns) == 0 {
// No annotations — just copy
anns = nil
}
if err := Annotate(ctx, AnnotateConfig{
InputPath: p.input,
OutputPath: p.output,
Annotations: anns,
}); err != nil {
return nil, fmt.Errorf("annotate %s: %w", p.typ, err)
}
}
return annotated, nil
}
// annotatedPath derives the annotated output path from the original.
func annotatedPath(original string) string {
ext := filepath.Ext(original)
base := strings.TrimSuffix(original, ext)
return base + "_annotated" + ext
}
View on GitHub (pinned to fc36c76c05)