# Log estimated pack size and full error on every push attempt

`8b60c38`→[main](/content/gh/entireio/git-sync/commits/main/index.html)·

Soph·2mo ago·1 file·+18 added/-0 removed

Two new --verbose log lines so the sequence of bootstrap pushes is visible end-to-end and we can tell whether a server error is a disguised body-size issue:

\- "bootstrap batch push attempting" before each PushPack call, carrying the header-derived size estimate (objects × 750 bytes) and the configured target limit. Lets you see the trajectory of pack sizes across subdivisions: 1.6 GB → 800 MB → 400 MB ...

\- "bootstrap batch push failed" on every failure, with the same estimate plus a will_subdivide flag and the full err.Error() (which already includes status code, Cf-Ray, and response body via gitproto.httpError). Previously we only saw the propagated final error; intermediate failures were silent unless they happened to match the body-limit heuristic.

checkPackSizeAndSubdivide now also returns the estimate so the caller can attach it to the "attempting" log even when no subdivision was triggered.

## Sessions

ab515220b2c8View transcript

[?\\can you rebase soph/progress-indicators onto soph/smart-subdivisionClaude Code·Opus 4.7[1m]·1 step](/content/gh/entireio/git-sync/session/3ee1ca7a-a436-44c1-906a-a912c6d33f96#timeline-ab515220b2c8/index.html)

## Changes

1

- internal/strategy/bootstrap

- Mbootstrap.go+18

```
390 unmodified lines

391
392
393
394
395
396
397
398
399
400
401
402
403
404
1 unmodified line

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

390 unmodified lines

continue // retry at same idx with new (smaller) checkpoint
				}
			}
			p.log("bootstrap batch push attempting",
				"branch", batch.Plan.TargetRef.String(),
				"batch", idx+1,
				"batch_total", len(batch.Checkpoints),
				"estimated_bytes", packObjectCount*calibratedBytesPerObject,
				"object_count", packObjectCount,
				"target_limit_bytes", p.TargetMaxPack,
				"calibrated_bytes_per_object", calibratedBytesPerObject)

cmds := convert.PlansToPushCommands(stagePlans)
			counter := &packReadCounter{ReadCloser: packReader}
1 unmodified line

sentBytes := counter.n
			if pushErr != nil {
				_ = packReader.Close()
				p.log("bootstrap batch push failed",
					"branch", batch.Plan.TargetRef.String(),
					"batch", idx+1,
					"batch_total", len(batch.Checkpoints),
					"estimated_bytes", packObjectCount*calibratedBytesPerObject,
					"target_limit_bytes", p.TargetMaxPack,
					"sent_bytes", sentBytes,
					"object_count", packObjectCount,
					"will_subdivide", isTargetBodyLimitError(pushErr) && len(batch.chain) > 0,
					"error", pushErr.Error())
				if isTargetBodyLimitError(pushErr) && len(batch.chain) > 0 {
					limit := p.TargetMaxPack
					if parsed := targetBodyLimit(pushErr); parsed > 0 {
