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

  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.