kovidgoyal/kitty · warning
failed to read cached image metadata: %w
Error message
failed to read cached image metadata: %w
What it means
load_image failed to os.ReadFile the file path stored under the IMAGE_METADATA_KEY entry of the kitten's cached data map. The metadata file path comes from a previous render's cache, so the read fails when that file was deleted, moved, or is unreadable (permissions, expired temp file).
Source
Thrown at kittens/choose_files/image_preview.go:94
func (p *ImagePreview) String() string {
return fmt.Sprintf("ImagePreview{%#v, ready: %v, renderer: %s}", p.abspath, p.ready.Load(), p.renderer.String())
}
func (p *ImagePreview) IsValidForColorScheme(bool) bool { return true }
func (p *ImagePreview) IsReady() bool { return p.ready.Load() || p.render_channel == nil }
func (p *ImagePreview) Unload() {
p.source_img = nil
}
func load_image(cached_data map[string]string) (img *images.ImageData, err error) {
fp := cached_data[IMAGE_METADATA_KEY]
if fp == "" {
return nil, fmt.Errorf("missing cached image metadata")
}
b, err := os.ReadFile(fp)
if err != nil {
return nil, fmt.Errorf("failed to read cached image metadata: %w", err)
}
var m images.SerializableImageMetadata
if err = json.Unmarshal(b, &m); err != nil {
return nil, fmt.Errorf("failed to decode cached image metadata: %w", err)
}
frames := make([][]byte, len(m.Frames))
for i := range m.Frames {
path := cached_data[IMAGE_DATA_PREFIX+strconv.Itoa(i)]
if path == "" {
return nil, fmt.Errorf("missing cached data for frame: %d", i)
}
d, e := os.ReadFile(path)
if e != nil {
return nil, fmt.Errorf("failed to read cached image frame %d data: %w", i, e)
}
m.Frames[i].Size = len(d)
frames[i] = d
}View on GitHub (pinned to 6d5d0c4406)
Solutions
- Retry the render without the cache (delete the stale cache entry so the image is re-rendered from source)
- Verify the path in cached_data[IMAGE_METADATA_KEY] exists before calling load_image
- Check permissions on the kitty cache directory
Example fix
// before
b, err := os.ReadFile(fp)
// after
if _, err := os.Stat(fp); err != nil {
return nil, fmt.Errorf("cached metadata missing, re-render needed: %w", err)
}
b, err := os.ReadFile(fp) Defensive patterns
Strategy: validation
Validate before calling
if fp := cached_data[IMAGE_METADATA_KEY]; fp != "" { if _, err := os.Stat(fp); err != nil { /* drop cache, re-render */ } } Try / catch
In Go: if err != nil && errors.Is(err, fs.ErrNotExist) { invalidate cache; fall back to full render } else { return err } Prevention
- Stat cached file paths before reading them
- Treat the preview cache as disposable and re-render on any cache error
When it happens
Trigger: Calling RenderImagePreview or ensure_source_image after the cached metadata JSON file referenced by cached_data[IMAGE_METADATA_KEY] no longer exists or cannot be read (e.g. kitty's cache dir was cleaned between renders).
Common situations: Temp/cache directory cleaned by OS or user while a choose-files preview is still active; multi-instance kittens sharing cache paths; file removed by another process.
Related errors
- failed to read cached image frame %d data: %w
- missing cached data for frame: %d
- No cache found and max cache age is negative
- failed to decode cached image metadata: %w
- failed to read the directory %s with error: %w
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/7edb6ea4a3dc051d.
Report an issue: GitHub.