# Use MaxPackBytes not BatchMaxPack as per-fetch abort threshold

`3a8d57c`→[main](/content/gh/entireio/git-sync/commits/main/index.html)·
  
Soph·3mo ago·1 file·+8 added/-5 removed

BatchMaxPack controls checkpoint placement (how many batches to plan).  
MaxPackBytes is the user's hard abort threshold for any single source fetch. The previous code used min(BatchMaxPack, MaxPackBytes) as the per-fetch limit, which meant a batch whose actual pack exceeded the planning estimate was aborted at the source-fetch stage before the target even saw it.

With estimate-based planning, the estimate can undercount (8 KiB/commit vs linux's real ~66 KiB/commit), so a batch legitimately exceeds the planning heuristic. The fetch should still complete — if the resulting pack is too large for the target's receive-pack, the push fails and bootstrap resume handles retry. Aborting early at the source side just wastes the transfer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

## Sessions

589898e25466View transcript

[?\\what test coverage do we have now for replicate?Claude Code·Opus 4.6[1m]·1 step](/content/gh/entireio/git-sync/session/7b2777b1-8075-41f4-a62a-cbfc1b76c01b#timeline-589898e25466/index.html)

## Changes

1. internal/strategy/bootstrap

- Mbootstrap.go+8/-5

```
196 unmodified lines

197
198
199
200
201
202
203
200
201
202
203
204
205
206
207
208
209
35 unmodified lines

245
246
247
245
248
249
250
251

196 unmodified lines

}
	}

batchLimit := p.BatchMaxPack
	if p.MaxPackBytes > 0 && (batchLimit == 0 || p.MaxPackBytes < batchLimit) {
		batchLimit = p.MaxPackBytes
	}
	// MaxPackBytes is the hard abort threshold for any single source fetch.
	// BatchMaxPack controls checkpoint *placement* (how many batches) but
	// should not cap individual fetches — the estimate may undercount, and
	// the actual pack for a batch can legitimately exceed the planning
	// heuristic. If the resulting pack is too large for the target's
	// receive-pack, the push itself fails and resume handles retry.
	fetchLimit := p.MaxPackBytes

for _, batch := range batches {
		result.PlannedBatchCount += len(batch.Checkpoints)
35 unmodified lines

})
	}

packReader, err := packReaderForCheckpoint(ctx, p, batch, checkpoint, current, batchLimit)
	packReader, err := packReaderForCheckpoint(ctx, p, batch, checkpoint, current, fetchLimit)
	if err != nil {
		return result, fmt.Errorf("fetch source batch pack for %s: %w", batch.Plan.TargetRef, err)
	}
```

Minternal/strategy/bootstrap/bootstrap.go+8/-5
