kovidgoyal/kitty · error

Failed to open image data output file

Error message

Failed to open image data output file: %s with error: %w

What it means

In the shared-memory transmission path, icat tried to os.Open the frame's on-disk file (frame.filename) before copying it into an shm segment, and the open failed.

Solutions

  1. Check that the intermediate file still exists and is readable when transmission starts
  2. Avoid aggressive temp-dir cleaners (systemd-tmpfiles, TMPDIR cleaner daemons) for icat runs
  3. Retry the icat invocation; transient races usually clear
Defensive patterns

Strategy: retry

Validate before calling

if _, err := os.Stat(frameFile); err != nil { /* regenerate frame before transmit */ }

Try / catch

if err != nil && strings.Contains(err.Error(), "Failed to open image data output file") { /* regenerate and retry once */ }

Prevention

When it happens

Trigger: Frame data was written to a temp file that has been deleted or is unreadable (permissions, ENOENT) by the time transmit_shm runs.

Common situations: Temp cleanup races on busy systems; file removed by concurrent process; permission mismatch when running under different users; disk-backed tempdir issues.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at kittens/icat/transmit.go:91

	} else {
		gc.SetAction(graphics.GRT_action_frame)
		gc.SetGap(int32(frame.delay_ms))
		gc.SetCompositionMode(utils.IfElse(frame.replace, graphics.Overwrite, graphics.AlphaBlend))
		if frame.compose_onto > 0 {
			gc.SetOverlaidFrame(uint64(frame.compose_onto))
		}
		gc.SetLeftEdge(uint64(frame.left)).SetTopEdge(uint64(frame.top))
	}
	return gc
}

func transmit_shm(imgd *image_data, frame_num int, frame *image_frame) (err error) {
	var mmap shm.MMap
	var data_size int64
	if frame.in_memory_bytes == nil {
		f, err := os.Open(frame.filename)
		if err != nil {
			return fmt.Errorf("Failed to open image data output file: %s with error: %w", frame.filename, err)
		}
		defer f.Close()
		if data_size, err = f.Seek(0, io.SeekEnd); err != nil {
			return fmt.Errorf("Failed to seek in image data output file: %s with error: %w", frame.filename, err)
		}
		if _, err = f.Seek(0, io.SeekStart); err != nil {
			return fmt.Errorf("Failed to seek in image data output file: %s with error: %w", frame.filename, err)
		}
		if mmap, err = shm.CreateTemp("icat-*", uint64(data_size)); err != nil {
			return fmt.Errorf("Failed to create a SHM file for transmission: %w", err)
		}
		if _, err = io.ReadFull(f, mmap.Slice()); err != nil {
			mmap.Close()
			mmap.Unlink()
			return fmt.Errorf("Failed to read data from image output data file: %w", err)
		}
	} else {
		data_size = int64(len(frame.in_memory_bytes))

View on GitHub (pinned to 6d5d0c4406)