AlistGo/alist · warning

failed to open image: %w

Error message

failed to open image: %w

What it means

generateThumbnailWithImagingOptimized calls os.Open on the image path and Go's standard library failed. The wrapped *PathError explains the cause: ENOENT (file removed since listing), EACCES (permission denied for the process user), or EMFILE (too many open file descriptors under heavy thumbnail traffic).

Source

Thrown at drivers/local/util.go:121

		WithOutput(outBuffer, os.Stderr). // Capture stdout to outBuffer, stderr to os.Stderr
		// ErrorToStdOut(). // Alternative: send ffmpeg's stderr to Go's stdout
		Run()

	if err != nil {
		return nil, fmt.Errorf("ffmpeg-go failed to resize image %s to buffer: %w", inputFile, err)
	}
	if outBuffer == nil || outBuffer.Len() == 0 {
		return nil, fmt.Errorf("ffmpeg-go produced empty buffer for %s", inputFile)
	}

	return outBuffer, nil
}

func generateThumbnailWithImagingOptimized(imagePath string, targetWidth int, quality int) (*bytes.Buffer, error) {

	file, err := os.Open(imagePath)
	if err != nil {
		return nil, fmt.Errorf("failed to open image: %w", err)
	}
	defer file.Close()

	img, err := imaging.Decode(file, imaging.AutoOrientation(true))
	if err != nil {
		return nil, fmt.Errorf("failed to decode image: %w", err)
	}

	thumbImg := imaging.Resize(img, targetWidth, 0, imaging.Lanczos)
	img = nil

	var buf bytes.Buffer
	// imaging.Encode
	// imaging.PNG, imaging.JPEG, imaging.GIF, imaging.BMP, imaging.TIFF
	outputFormat := imaging.JPEG
	encodeOptions := []imaging.EncodeOption{imaging.JPEGQuality(quality)}

	// outputFormat := imaging.PNG

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Check the wrapped PathError for the syscall reason (no such file / permission denied / too many open files)
  2. Confirm the process user can read the file: sudo -u <alistuser> head -c1 <path>
  3. If EMFILE, raise the file descriptor limit (ulimit -n / LimitNOFILE) or reduce concurrent thumbnail workers
  4. If files are transiently missing, treat the error as non-fatal and skip caching the thumbnail
Defensive patterns

Strategy: validation

Validate before calling

func canRead(path string) bool {
    f, err := os.Open(path)
    if err != nil {
        return false
    }
    f.Close()
    return true
}

Try / catch

Check errors.Is(err, fs.ErrNotExist) || errors.Is(err, fs.ErrPermission): for ErrNotExist skip silently (file raced away); for ErrPermission log once per directory; for EMFILE throttle concurrency.

Prevention

When it happens

Trigger: Thumbnail request racing with file deletion, read permissions not granted to the alist/OpenList process user, NFS/SMB mount not yet mounted or stale, or fd exhaustion when many thumbnails are generated concurrently.

Common situations: Media directory on a network mount that dropped; files renamed/deleted by another process between list and thumb requests; systemd/docker service user lacking read access to the media folder.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/d3efbe53b172f832. Report an issue: GitHub.