Billionmail/BillionMail · error
annotate %s: %w
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.
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)
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: %w\noutput: %s
- imagemagick thumbnail failed: %w output: %s
- failed to update BILLIONMAIL_HOSTNAME in postfix container:
- Failed to generate DKIM key pair: %v
- failed to hash postfix config: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/721b87c0531ef2e1.
Report an issue: GitHub.