kovidgoyal/kitty · warning

failed to read cached image metadata

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).

Solutions

  1. Retry the render without the cache (delete the stale cache entry so the image is re-rendered from source)
  2. Verify the path in cached_data[IMAGE_METADATA_KEY] exists before calling load_image
  3. 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

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


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/7edb6ea4a3dc051d. Report an issue: GitHub.

Appendix: 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)