kopia/kopia · error

pack offset is too high

Error message

pack offset %v is too high

What it means

The v2 index encodes each entry's pack offset in a fixed bit field capped at v2MaxPackOffset. During index building, if the largest pack offset across all contents (computed by maxContentLengths) exceeds that cap, the offset cannot be represented and building fails with this error. It indicates a single pack file is too large for the v2 entry encoding.

Solutions

  1. Split the oversized pack into smaller packs so all offsets stay below v2MaxPackOffset.
  2. Cap pack file size in the writer/packager configuration to keep offsets within the encodable range.
  3. Check v2MaxPackOffset in index_v2.go to confirm the exact byte threshold the offending pack exceeds.
  4. Re-pack contents that were appended into a very large pack before rebuilding the index.
Defensive patterns

Strategy: validation

Validate before calling

_, _, maxOff := maxContentLengths(infos)
if maxOff >= v2MaxPackOffset {
    // re-pack: split the oversized pack so offsets stay under the cap
}

Try / catch

if err := buildIndex(infos); err != nil && strings.Contains(err.Error(), "pack offset") {
    // split the offending pack file and rebuild the index
}

Prevention

When it happens

Trigger: Building a v2 index where maxPackOffset >= v2MaxPackOffset — i.e. some content lives at an offset inside its pack file beyond the maximum encodable offset (a very large pack, roughly at/above the 256 MiB scale).

Common situations: Oversized pack files produced by huge writes or unbounded compaction, then indexed into a v2 index segment.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at repo/content/index/index_v2.go:470

	if len(packID2Index) > v2MaxShortPackIDCount {
		entrySize = max(entrySize, v2EntryOffsetExtendedPackBlobIDEnd)
	}

	// compute maximum content length to determine how many bits we need to use to store it.
	maxPackedLen, maxOriginalLength, maxPackOffset := maxContentLengths(sortedInfos)

	// contents >= 28 bits (256 MiB) can't be stored at all.
	if maxPackedLen >= v2MaxContentLength || maxOriginalLength >= v2MaxContentLength {
		return nil, errors.Errorf("maximum content length is too high: (packed %v, original %v, max %v)", maxPackedLen, maxOriginalLength, v2MaxContentLength)
	}

	// contents >= 24 bits (16 MiB) requires extra 0.5 byte per length.
	if maxPackedLen >= v2MaxShortContentLength || maxOriginalLength >= v2MaxShortContentLength {
		entrySize = max(entrySize, v2EntryOffsetHighLengthBitsEnd)
	}

	if maxPackOffset >= v2MaxPackOffset {
		return nil, errors.Errorf("pack offset %v is too high", maxPackOffset)
	}

	keyLength := -1

	if len(sortedInfos) > 0 {
		var hashBuf [maxContentIDSize]byte

		keyLength = len(contentIDToBytes(hashBuf[:0], sortedInfos[0].ContentID))
	}

	return &indexBuilderV2{
		packBlobIDOffsets:      map[blob.ID]uint32{},
		keyLength:              keyLength,
		entrySize:              entrySize,
		entryCount:             len(sortedInfos),
		uniqueFormatInfo2Index: uniqueFormat2Index,
		packID2Index:           packID2Index,
	}, nil

View on GitHub (pinned to 82495e54b5)