kovidgoyal/kitty · warning

Failed to unmap history buffer segment: %s

Error message

Failed to unmap history buffer segment: %s

What it means

munmap of a scrollback (history buffer) segment failed; strerror(errno) explains why. The segment metadata is still zeroed, so this is a leak warning rather than a crash. Almost always indicates an internal bug or memory corruption.

Source

Thrown at kitty/history.c:47

    // https://github.com/kovidgoyal/kitty/pull/10254
    char *mem = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
    if (mem == MAP_FAILED) fatal("Out of memory allocating new history buffer segment");
    char *needs_free = mem;
    for (HistoryBufSegment *s = self->segments + self->num_segments; s < self->segments + self->num_segments + num; s++, mem += segment_size) {
        s->cpu_cells = (CPUCell *)mem;
        s->gpu_cells = (GPUCell *)(((uint8_t *)s->cpu_cells) + cpu_cells_size);
        s->line_attrs = (LineAttrs *)(((uint8_t *)s->gpu_cells) + gpu_cells_size);
        s->mem = NULL;
        s->mmap_size = 0;
    }
    self->segments[self->num_segments].mem = needs_free;
    self->segments[self->num_segments].mmap_size = mmap_size;
    self->num_segments += num;
}

static void
free_segment(HistoryBufSegment *s) {
    if (s->mem && munmap(s->mem, s->mmap_size) != 0) log_error("Failed to unmap history buffer segment: %s", strerror(errno));
    zero_at_ptr(s);
}

static index_type
segment_for(HistoryBuf *self, index_type y) {
    index_type seg_num = y / SEGMENT_SIZE;
    while (UNLIKELY(seg_num >= self->num_segments && SEGMENT_SIZE * self->num_segments < self->ynum)) add_segment(self, 1);
    if (UNLIKELY(seg_num >= self->num_segments)) fatal("Out of bounds access to history buffer line number: %u", y);
    return seg_num;
}

#define seg_ptr(which, stride)                             \
    {                                                      \
        index_type seg_num = segment_for(self, y);         \
        y -= seg_num * SEGMENT_SIZE;                       \
        return self->segments[seg_num].which + y * stride; \
    }

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Report upstream to kitty with reproduction steps - this indicates an internal bug
  2. Upgrade kitty to the latest version
  3. Rule out LD_PRELOAD allocator overrides or sanitizers
  4. Restart kitty if it recurs
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: free_segment during historybuf_clear or HistoryBuf dealloc when munmap(s->mem, s->mmap_size) returns non-zero - corrupted mmap_size, double unmap, or VM subsystem inconsistency.

Common situations: Essentially never seen in practice; would indicate memory corruption, a kitty bug, or unusual allocator/libc environments.

Related errors


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