kopia/kopia · warning

error unmapping index

Error message

error unmapping index %v (also had close error: %v)

What it means

This error is produced by the closer function returned from mmapFile (unix) when, after the file Close already failed, the subsequent mm.Unmap() also fails. The wrap includes the earlier close error so both failures are visible in one message. It indicates the process could not release the memory mapping — usually because the mapping was already invalidated or memory pressure/OS quirks prevented munmap from succeeding.

Solutions

  1. Read the embedded '(also had close error: %v)' portion to diagnose the original close failure first
  2. Ensure the closer is invoked exactly once per openIndex result; add sync.Once if double-close is possible
  3. Ignore if occurring during process exit — the OS reclaims mappings at exit
  4. If repeated, check for memory corruption or fs/driver issues on the cache mount

Example fix

// before: calling closer unconditionally on every path, possibly twice
closer(); defer cleanup()
// after: guarantee single invocation
var closeOnce sync.Once
dispose := func() { closeOnce.Do(func() { _ = closer() }) }
Defensive patterns

Strategy: try-catch

Try / catch

if err := closer(); err != nil {
    if strings.Contains(err.Error(), "unmapping index") {
        // likely double-invocation; make disposal idempotent
    }
    log.Printf("index teardown: %v", err)
}

Prevention

When it happens

Trigger: Calling the closer returned by openIndex on Unix when both f.Close() (reported via closeErr inside the message) and mm.Unmap() fail — e.g. double-closing the same index, or unmapping after the mapping was already torn down.

Common situations: Bugs where the closer is invoked twice on the same index, or teardown during abnormal shutdown when the process is being torn apart and syscalls start failing.

Related errors


AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07). Data as JSON: /api/errors/5b35a7944da01bb4. Report an issue: GitHub.

Appendix: source

Thrown at repo/content/committed_content_index_disk_cache_unix.go:36

	f, err := os.Open(filename) //nolint:gosec
	if err != nil {
		return nil, nil, errors.Wrap(err, "unable to open file despite retries")
	}

	mm, err := mmap.Map(f, mmap.RDONLY, 0)
	if err != nil {
		_ = f.Close()
		return nil, nil, errors.Wrap(err, "mmap error")
	}

	// On Unix, it's safe to close the FD now; the mapping remains valid.
	if err := f.Close(); err != nil {
		// If close fails, still return mapping, but report error on closer to surface the issue later.
		closeErr := errors.Wrapf(err, "error closing index %v after mmap", filename)

		return mm, func() error {
			if err2 := mm.Unmap(); err2 != nil {
				return errors.Wrapf(err2, "error unmapping index %v (also had close error: %v)", filename, closeErr)
			}

			return closeErr
		}, nil
	}

	return mm, func() error {
		if err2 := mm.Unmap(); err2 != nil {
			return errors.Wrapf(err2, "error unmapping index %v", filename)
		}

		return nil
	}, nil
}

View on GitHub (pinned to 82495e54b5)