plandex-ai/plandex · error
error getting num tokens: %v
Error message
error getting num tokens: %v
What it means
UpdateContexts computes the token count for each context being updated. For image contexts it calls shared.GetImageTokens, which base64-decodes the image body and parses its header to compute width/height-based token estimates. This error wraps any failure from that call — most commonly invalid base64 data or an undecodable/corrupt image header.
Source
Thrown at app/server/db/context_helpers_update.go:176
return
}
// log.Println("Got context", context.Id, "numTokens", context.NumTokens)
}
mu.Lock()
defer mu.Unlock()
contextsById[id] = context
updatedContexts = append(updatedContexts, context.ToApi())
if context.ContextType != shared.ContextMapType {
var updateNumTokens int
var err error
if context.ContextType == shared.ContextImageType {
updateNumTokens, err = shared.GetImageTokens(params.Body, context.ImageDetail)
if err != nil {
errCh <- fmt.Errorf("error getting num tokens: %v", err)
return
}
} else {
updateNumTokens = shared.GetNumTokensEstimate(params.Body)
// log.Println("len(params.Body)", len(params.Body))
}
// log.Println("Updating context", id, "updateNumTokens", updateNumTokens)
tokenDiff := updateNumTokens - context.NumTokens
tokenDiffsById[id] = tokenDiff
aggregateTokensDiff += tokenDiff
totalTokens += tokenDiff
totalPlannerTokens += tokenDiff
if !context.AutoLoaded {
totalBasicPlannerTokens += tokenDiff
aggregateBasicTokensDiff += tokenDiff
}View on GitHub (pinned to e2d772072e)
Solutions
- Strip the 'data:image/...;base64,' prefix and other non-base64 characters from params.Body before sending
- Verify the file is a real, complete image and in a format with a registered Go decoder (jpeg, png, gif); re-upload if truncated
- Check server logs for 'failed to decode base64 image data' vs 'failed to decode image config' to pinpoint which stage failed
- If using a newer format, ensure the corresponding image decoder package is imported for side effects in shared/images.go
Example fix
// before
body := "data:image/png;base64,iVBORw0KGgo..."
// after
body := strings.TrimPrefix(raw, "data:image/png;base64,")
if _, err := base64.StdEncoding.DecodeString(body); err != nil { return fmt.Errorf("invalid base64 image body") } Defensive patterns
Strategy: validation
Validate before calling
func validImageBody(b string) bool {
b = stripDataURIPrefix(b)
data, err := base64.StdEncoding.DecodeString(b)
if err != nil || len(data) == 0 { return false }
_, _, err = image.DecodeConfig(bytes.NewReader(data))
return err == nil
}
// call before UpdateContexts for each image context Type guard
func isDecodableImage(body string) (ok bool) {
defer func() { if recover() != nil { ok = false } }()
return validImageBody(body)
} Try / catch
if _, err := shared.GetImageTokens(params.Body, detail); err != nil {
log.Printf("skipping invalid image context %s: %v", id, err)
return nil // drop the context instead of failing the batch
} Prevention
- Strip data-URI prefixes and whitespace before base64-encoding image bodies
- Only send jpeg/png/gif images (formats with registered Go decoders)
- Validate with image.DecodeConfig client-side before uploading
- Check file completeness (truncated uploads fail header parsing)
When it happens
Trigger: An UpdateContexts request supplies an image-type context whose params.Body is not valid standard base64 (e.g. data-URI prefix like 'data:image/png;base64,' left in, whitespace/newlines, URL-safe base64) or whose decoded bytes are not a recognizable image format (image.DecodeConfig fails on truncated/corrupt/unsupported formats).
Common situations: Client sends a data URL instead of raw base64; image was truncated by an upload size limit; user attached a non-image file renamed to .png; an image format without a registered decoder (e.g. webp/avif without the decoder imported) is passed through.
Related errors
- failed to decode base64 image data: %w
- failed to check outdated context: %s
- no update request function provided
- error updating context: %v
- failed to check context conflicts: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/d22c3ecb35864669.
Report an issue: GitHub.