Skip to content

fix: correct Content-Range end byte in chunked upload (RFC 7233)#212

Open
chrisdebian wants to merge 2 commits into
mapilio:mainfrom
chrisdebian:fix/upload-content-range-header
Open

fix: correct Content-Range end byte in chunked upload (RFC 7233)#212
chrisdebian wants to merge 2 commits into
mapilio:mainfrom
chrisdebian:fix/upload-content-range-header

Conversation

@chrisdebian

Copy link
Copy Markdown
Contributor

Summary

  • Fixes MapSyncer issue Update README.md #87Invalid "Content-Range" provided error when uploading large tracks (>64 MB, i.e. more than one chunk).
  • The upload loop in upload_manager.py was sending bytes={offset}-{entity_size}/{entity_size} for every chunk. RFC 7233 requires the end value to be the last byte of the current chunk (0-indexed, inclusive), not the total file size. For multi-chunk uploads this meant every intermediate chunk carried an invalid range, causing the server to reject it.
  • Adds two unit tests: single-chunk and multi-chunk Content-Range header construction.

Root cause

# Before (wrong — end is total size, not chunk end):
"content-range": f"bytes={offset}-{self.entity_size}/{self.entity_size}"

# After (correct — end is last byte of this chunk):
chunk_end = (offset + len(chunk) - 1) if chunk else self.entity_size
"content-range": f"bytes={offset}-{chunk_end}/{self.entity_size}"

Related issues

Test plan

  • pytest tests/test_upload_manager.py — 2 new tests pass
  • Full suite: pytest — 97 tests pass
  • On-device: upload a sequence larger than 64 MB and confirm no Invalid Content-Range error

🤖 Generated with Claude Code

chrisdebian and others added 2 commits May 17, 2026 15:09
Hard-coded 4096x1344 values only work for one specific GoPro MAX
recording mode. Use exiftool computed-value syntax so CroppedArea
and FullPano tags are derived from actual ImageWidth/ImageHeight,
making the command work for any output resolution (e.g. 4096x2048).

CroppedAreaTopPixels = (ImageWidth/2 - ImageHeight) / 2

Closes mapilio#200
The upload loop was sending `bytes={offset}-{entity_size}/{entity_size}`
for every chunk. RFC 7233 requires the end value to be the last byte of
the *current chunk* (0-indexed, inclusive), not the total entity size.
For multi-chunk uploads this caused the server to reject intermediate
chunks with "Invalid Content-Range provided" (MapSyncer issue mapilio#87).

Fix: compute `chunk_end = offset + len(chunk) - 1` for non-empty chunks
and keep the existing sentinel value for the empty finalisation request.

Adds two unit tests covering single-chunk and multi-chunk Content-Range
header construction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@chrisdebian

Copy link
Copy Markdown
Contributor Author

Hi,

Just flagging that this is the root cause behind the MapSyncer upload failures reported in MapSyncer #87 and #89 — users hitting 'Invalid Content-Range' on any track over 64 MB. The fix and unit tests are ready whenever you have a moment to review.

Thanks, Chris

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant