{"record":{"id":"4c480348bdde6fa2","repo":"plandex-ai/plandex","slug":"failed-to-read-image-tokens-for-s-v","errorCode":null,"errorMessage":"failed to read image tokens for %s: %v","messagePattern":"failed to read image tokens for (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/context_shared.go","lineNumber":51,"sourceCode":"\nfunc getMapFileDetails(path string, size, mapSize int64) (mapFileDetails, error) {\n\tvar isImage bool\n\tvar totalMapSizeExceeded bool\n\n\tres := mapFileDetails{\n\t\tsize:                          size,\n\t\tmapFilesSkippedAfterSizeLimit: []string{},\n\t\tmapFilesTruncatedTooLarge:     []filePathWithSize{},\n\t}\n\n\tif !shared.HasFileMapSupport(path) {\n\t\tif shared.IsImageFile(path) {\n\t\t\tisImage = true\n\n\t\t\tvar err error\n\t\t\tres.tokens, err = readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024)\n\t\t\tif err != nil {\n\t\t\t\treturn mapFileDetails{}, fmt.Errorf(\"failed to read image tokens for %s: %v\", path, err)\n\t\t\t}\n\t\t} else {\n\t\t\tres.tokens = shared.GetBytesToTokensEstimate(size)\n\t\t}\n\t} else {\n\t\tvar truncated bool\n\t\tif size > shared.MaxContextMapSingleInputSize {\n\t\t\tsize = shared.MaxContextMapSingleInputSize\n\t\t\ttruncated = true\n\t\t\tres.tokens = shared.GetBytesToTokensEstimate(size)\n\t\t}\n\n\t\t// should go in either skip list *or* truncated list, not both\n\t\tif mapSize+size > shared.MaxContextMapTotalInputSize {\n\t\t\ttotalMapSizeExceeded = true\n\t\t\tres.mapFilesSkippedAfterSizeLimit = append(res.mapFilesSkippedAfterSizeLimit, path)\n\t\t\tres.tokens = shared.GetBytesToTokensEstimate(size)\n\t\t} else if truncated {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/context_shared.go#L33-L69","documentation":"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.","triggerScenarios":"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.","commonSituations":"Binary/corrupt files that pass the image-extension check; permission-denied image files; zero-byte or truncated images copied from a failed download.","solutions":["Verify the image file opens and is a valid image (file/permissions check)","Remove the corrupt or non-image file from the context paths","If the file is legitimately an image, re-copy or re-download it"],"exampleFix":"// before\nres.tokens, err = readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024)\nif err != nil {\n    return mapFileDetails{}, fmt.Errorf(\"failed to read image tokens for %s: %v\", path, err)\n}\n// after — fall back to byte-based estimate instead of failing\nres.tokens, err = readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024)\nif err != nil {\n    res.tokens = shared.GetImageTokensEstimateFromBytes(size)\n}","handlingStrategy":"fallback","validationCode":"if shared.IsImageFile(path) {\n    f, err := os.Open(path)\n    if err != nil {\n        return fmt.Errorf(\"image %s unreadable: %w\", path, err)\n    }\n    f.Close()\n}","typeGuard":"func isReadableImage(path string) bool {\n    if !shared.IsImageFile(path) { return false }\n    f, err := os.Open(path)\n    if err != nil { return false }\n    defer f.Close()\n    head := make([]byte, 8)\n    _, err = f.Read(head)\n    return err == nil\n}","tryCatchPattern":"tokens, err := readImageTokensForDefsOnly(path, size, openai.ImageURLDetailHigh, 8*1024)\nif err != nil {\n    tokens = shared.GetImageTokensEstimateFromBytes(size) // graceful fallback\n}","preventionTips":["Verify image files open correctly before adding them to context","Remove corrupt/zero-byte images from repos used with the tool","Keep image extensions honest (don't rename text files to .png)"],"tags":["image","filesystem","tokens"],"backgroundTag":"image-file-unreadable","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}