Billionmail/BillionMail · error
create thumbnail dir: %w
Error message
create thumbnail dir: %w
What it means
GenerateThumbnail creates the parent directory of cfg.OutputPath via os.MkdirAll before invoking ImageMagick. If directory creation fails (permissions, read-only fs, path is a file), the OS error is wrapped with 'create thumbnail dir: %w'.
Source
Thrown at core/internal/service/video_gen/thumbnail.go:58
}
h := cfg.Height
if h == 0 {
h = defaultThumbHeight
}
return []string{
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
- Inspect the wrapped OS error for the exact filesystem cause
- Ensure the thumbnail output directory exists and is writable by the process user
- Mount a writable volume for output paths in containers
- Verify OutputPath is constructed correctly (non-empty base dir, directory not a file)
Example fix
// before
if err := os.MkdirAll(filepath.Dir(cfg.OutputPath), 0755); err != nil {
return "", fmt.Errorf("create thumbnail dir: %w", err)
}
// after
outDir := filepath.Dir(cfg.OutputPath)
if info, err := os.Stat(outDir); err == nil && !info.IsDir() {
return "", fmt.Errorf("thumbnail output path %q is a file, not a directory", outDir)
}
if err := os.MkdirAll(outDir, 0755); err != nil {
return "", fmt.Errorf("create thumbnail dir: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
outDir := filepath.Dir(cfg.OutputPath)
if outDir == "." || outDir == "" {
return fmt.Errorf("thumbnail output path has no directory component")
}
if info, err := os.Stat(outDir); err == nil && !info.IsDir() {
return fmt.Errorf("%s is a file", outDir)
} Try / catch
path, err := GenerateThumbnail(ctx, cfg)
if err != nil && strings.HasPrefix(err.Error(), "create thumbnail dir:") {
var perr *fs.PathError
if errors.As(err, &perr) && errors.Is(perr.Err, fs.ErrPermission) {
return fmt.Errorf("cannot write thumbnails to %s: check volume mount/permissions", filepath.Dir(cfg.OutputPath))
}
} Prevention
- Derive thumbnail output paths from the same writable volume as screenshot output
- Pre-create output directories during deployment
- Run tests (e.g. TestGenerateThumbnail_NonexistentInput) in CI to catch path bugs early
- Avoid empty/relative base dirs when composing OutputPath
When it happens
Trigger: os.MkdirAll(filepath.Dir(cfg.OutputPath), 0755) fails: the parent of OutputPath is unwritable, already exists as a file, disk is full, or an invalid path segment is supplied.
Common situations: Same writable-volume issues as screenshot output in Docker; OutputPath built by joining a bad/empty base dir so Dir() resolves to an unwritable location; non-root process user lacking permissions.
Related errors
- create output dir: %w
- error reading project configuration file: %v
- error writing project configuration file: %v
- error writing knowledge base file: %v
- error reading knowledge base directory: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/b003a84c3bedc459.
Report an issue: GitHub.