plandex-ai/plandex · error

failed to get image tokens for %s: %v

Error message

failed to get image tokens for %s: %v

What it means

Thrown when shared.GetImageTokens fails to compute the token cost of an image file that is part of a file-type context. The library uses this only when the file is classified as an image (IsImageFile) and its content changed, so tokenization of the base64 payload failed. The wrapped %v carries the decoder/model-limit error.

Source

Thrown at app/cli/lib/context_update.go:454

						filesSkippedAfterSizeLimit = append(filesSkippedAfterSizeLimit, ctx.FilePath)
						return
					}

					// Accept
					mu.Lock()
					totalSize += size
					totalContextCount++
					totalBodySize += (newBodySize - oldBodySize)
					mu.Unlock()

					var numTokens int
					if shared.IsImageFile(ctx.FilePath) {
						tokens, err := shared.GetImageTokens(base64.StdEncoding.EncodeToString(fileContent), ctx.ImageDetail)
						if err != nil {
							mu.Lock()
							defer mu.Unlock()
							errs = append(errs, fmt.Errorf("failed to get image tokens for %s: %v", ctx.FilePath, err))
							return
						}
						numTokens = tokens
					} else {
						numTokens = shared.GetNumTokensEstimate(string(fileContent))
					}

					mu.Lock()
					defer mu.Unlock()

					tokenDiffsById[ctx.Id] = numTokens - ctx.NumTokens
					numFiles++
					updatedContexts = append(updatedContexts, ctx)

					reqFns[ctx.Id] = func() (*shared.UpdateContextParams, error) {
						return &shared.UpdateContextParams{
							Body: string(fileContent),
						}, nil

View on GitHub (pinned to e2d772072e)

Solutions

  1. Open/validate the image locally; re-export or replace the corrupted file.
  2. Downscale the image so it fits the provider's max dimensions/size for vision tokens.
  3. Verify the file extension matches the actual format (IsImageFile dispatches on extension).
  4. If the file should not be treated as an image, rename it or remove it from context.
Defensive patterns

Strategy: validation

Validate before calling

f, err := os.Open(imgPath)
if err != nil { return err }
_, format, err := image.DecodeConfig(f)
if err != nil { return fmt.Errorf("%s is not a decodable image: %w", imgPath, err) }
if format == "" || imgTooLargeForVision(format) { fix before adding to context }

Type guard

func isUsableImage(path string) bool {
    f, err := os.Open(path)
    if err != nil { return false }
    defer f.Close()
    _, _, err = image.DecodeConfig(f)
    return err == nil
}

Prevention

When it happens

Trigger: A changed image file (SHA differs from ctx.Sha) is passed with its ImageDetail setting to shared.GetImageTokens, which returns an error — e.g. the bytes are not a valid image, the image exceeds the API's dimension/size limits, or the encoded payload is empty.

Common situations: Corrupt or truncated image committed to the repo; image format extension mismatch (e.g. .png containing WebP); image too large in pixels for the provider's vision API; invalid ImageDetail value stored on the context; zero-byte image files created by failed exports.

Related errors


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