plandex-ai/plandex · error

failed to read image tokens for %s: %v

Error message

failed to read image tokens for %s: %v

What it means

getMapFileDetails detects image files via shared.IsImageFile and estimates their token count with readImageTokensForDefsOnly. If that fails (file unreadable or header parse error), the failure is wrapped with this message naming the image path. It means the image could not be tokenized for the file map.

Source

Thrown at app/cli/lib/context_shared.go:51

func getMapFileDetails(path string, size, mapSize int64) (mapFileDetails, error) {
	var isImage bool
	var totalMapSizeExceeded bool

	res := mapFileDetails{
		size:                          size,
		mapFilesSkippedAfterSizeLimit: []string{},
		mapFilesTruncatedTooLarge:     []filePathWithSize{},
	}

	if !shared.HasFileMapSupport(path) {
		if shared.IsImageFile(path) {
			isImage = true

			var err error
			res.tokens, err = readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024)
			if err != nil {
				return mapFileDetails{}, fmt.Errorf("failed to read image tokens for %s: %v", path, err)
			}
		} else {
			res.tokens = shared.GetBytesToTokensEstimate(size)
		}
	} else {
		var truncated bool
		if size > shared.MaxContextMapSingleInputSize {
			size = shared.MaxContextMapSingleInputSize
			truncated = true
			res.tokens = shared.GetBytesToTokensEstimate(size)
		}

		// should go in either skip list *or* truncated list, not both
		if mapSize+size > shared.MaxContextMapTotalInputSize {
			totalMapSizeExceeded = true
			res.mapFilesSkippedAfterSizeLimit = append(res.mapFilesSkippedAfterSizeLimit, path)
			res.tokens = shared.GetBytesToTokensEstimate(size)
		} else if truncated {

View on GitHub (pinned to e2d772072e)

Solutions

  1. Verify the image file opens and is a valid image (file/permissions check)
  2. Remove the corrupt or non-image file from the context paths
  3. If the file is legitimately an image, re-copy or re-download it

Example fix

// before
res.tokens, err = readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024)
if err != nil {
    return mapFileDetails{}, fmt.Errorf("failed to read image tokens for %s: %v", path, err)
}
// after — fall back to byte-based estimate instead of failing
res.tokens, err = readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024)
if err != nil {
    res.tokens = shared.GetImageTokensEstimateFromBytes(size)
}
Defensive patterns

Strategy: fallback

Validate before calling

if shared.IsImageFile(path) {
    f, err := os.Open(path)
    if err != nil {
        return fmt.Errorf("image %s unreadable: %w", path, err)
    }
    f.Close()
}

Type guard

func isReadableImage(path string) bool {
    if !shared.IsImageFile(path) { return false }
    f, err := os.Open(path)
    if err != nil { return false }
    defer f.Close()
    head := make([]byte, 8)
    _, err = f.Read(head)
    return err == nil
}

Try / catch

tokens, err := readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024)
if err != nil {
    tokens = shared.GetImageTokensEstimateFromBytes(size) // graceful fallback
}

Prevention

When it happens

Trigger: shared.IsImageFile(path) is true and readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024) returns an error — os.Open failure or GetImageTokensFromHeader failure on a corrupt/truncated image header.

Common situations: Binary/corrupt files that pass the image-extension check; permission-denied image files; zero-byte or truncated images copied from a failed download.

Related errors


AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05). Data as JSON: /api/errors/4c480348bdde6fa2. Report an issue: GitHub.