Coding Agents & Terminal · recorded 2026-08-29 · applies to 1 tool(s) ✓ Verified

Problem: curl resume fails: (33) HTTP server does not seem to support byte ranges —— Trove problem library

Verified 2026-08-29interrupted curl downloads can't resume — probe with a Range header first (206 = supported); if supported use `curl -C -`, otherwise switch source or redownload.

Quick fix

# One-liner: probe whether the server supports Range first (206=supported, 200=not)
curl -sI -H "Range: bytes=0-99" URL

If supported, resume with curl -C - -o file URL; if not, switch sources or re-download the whole package.

What you will run into

After a large download (model, image, dataset) is interrupted, you try to resume:

$ curl -C - -o model.bin https://example.com/model.bin
** Resuming transfer from byte position 10485760
curl: (33) HTTP server does not seem to support byte ranges. Cannot resume.

Signs: curl -C - resumes from the downloaded position, but the server doesn't support Range requests (or ignores Range and returns the full 200); after error 33 curl exits, leaving the file partial; wget -c fails the same way.

Why this happens

HTTP resumable download depends on the Range header: the client sends Range: bytes=N-, the server returns 206 Partial Content + Content-Range.

When the server doesn't support it (returns 200 full or 416), curl can't stitch and can only report 33 and give up.

Common with: small self-hosted servers / intranet download sites, python3 -m http.server (3.14 measured: no Range support), some cloud-drive direct links.

ServerRange support
nginx / CDN / object storageSupported (default)
python3 -m http.server (3.14)Not supported (measured)
Small self-hosted / drive direct linksDepends on the implementation

Resumable download is protocol negotiation between "client Range + server 206": curl sends Range: bytes=N-; a supporting server returns 206 Partial Content + Content-Range telling it where to resume;

an unsupported server returns 200 (full body) or 416 (invalid range) — curl cannot splice onto a "200 full restart", so it gives up with error 33. A resume failure therefore means the server does not implement Range, not a curl or network problem.

python3 -m http.server (3.14, tested) does not support Range; nginx/CDNs/object storage do by default.

Deterministic takeaway: on curl -C - error 33, probe the server first: curl -I -H "Range: bytes=0-0" <url> — 206 means resumable, 200/416 means not;

for the latter, switch download channels (nginx/CDN/object storage) or use a tool that handles it (wget -c uses the same protocol and still depends on 206); fixed diagnostic: the failure is never on the client side.

Step by step

1. Probe whether the server supports Range first — Diagnose

curl -sI -H "Range: bytes=0-99" URL

206 = supported, 200 = not supported.

2. If supported, resume — Required

curl -C - -o file URL

Continues automatically from the existing file size; wget uses wget -c URL.

3. Sources without Range support — Required

Switch to a Range-supporting source (CDN/object storage/official mirror); or aria2c -c URL (multi-threaded segmented download, pickier about the source); or re-download the whole package (delete the partial file to avoid misusing an incomplete one).

4. Handle 33 in scripts — Required

curl -C - -o file URL || echo "resume failed, check server Range support"

In download tools/scripts, check -C -'s return code first; alert on 33 instead of silently treating it as success; always verify the hash after a completed resume (md5sum -c / sha256) - misaligned stitching of partial files is very subtle.

How to confirm it works

Resume succeeds and the hash matches (measured output shape):

curl -C - -o part.bin URL
-> exit 0, md5 matches the source file (measured 4211ba8d)

Failure chain: a server without Range support -> curl: (33) exit 33 (measured, same as packer#136).

Other environments

EnvironmentNotes
Range supportedcurl -C - resumes directly (measured 206 + Content-Range chain)
Range not supportedSwitch source / aria2c / full re-download
python3 -m http.server3.14 measured: no Range support; don't use for local debugging
Probing methodcurl -sI -H "Range: bytes=0-99", 206 vs 200
Local testingUse nginx (supports by default) or a self-written 206 server

Symptom

After a large download (model, image, dataset) is interrupted, you try to resume:

$ curl -C - -o model.bin https://example.com/model.bin
** Resuming transfer from byte position 10485760
curl: (33) HTTP server does not seem to support byte ranges. Cannot resume.

Signs: curl -C - resumes from the downloaded position, but the server doesn't support Range requests (or ignores Range and returns 200 full); after error 33 curl exits, leaving the file partial; wget -c fails the same way.

Cause

HTTP resumable download depends on the Range header: the client sends Range: bytes=N-, the server returns 206 Partial Content + Content-Range. When the server doesn't support it (returns 200 full or 416), curl can't stitch and can only report 33 and give up. Common with: small self-hosted servers / intranet download sites, python3 -m http.server (3.14 measured: no Range support), some cloud-drive direct links. Note: python's http.server no longer supports Range in new versions - don't use it for local resumable-download debugging.

Solution

  1. Probe whether the server supports Range first: curl -sI -H "Range: bytes=0-99" URL - 206 supported, 200 not.
  2. If supported, resume: curl -C - -o file URL (continues from the existing file size automatically); wget uses wget -c URL.
  3. Sources without Range support: switch to a Range-supporting source (CDN/object storage/official mirror); or aria2c (aria2c -c URL, multi-threaded segmented, pickier about the source); or re-download the whole package (delete the partial file to avoid misusing an incomplete one).
  4. In download tools/scripts: check -C -'s return code first, alert on 33 instead of silently treating it as success; always verify the hash after a completed resume (md5sum -c / sha256) - misaligned stitching of partial files is very subtle.
  5. Local resumable-download testing: use nginx (supports Range by default) or a self-written 206 server; don't use python3 -m http.server.
Verification Evidence
  • Local measurement (2026-08-29, WSL Ubuntu, curl 8.x, 50MB random file, fully local):
  • Success chain: self-written Range-supporting server (206 + Content-Range) -> timeout 0.3 curl -o part.bin interrupted at a 15.5MB partial -> curl -C - -o part.bin resumed exit 0, md5 matches the source file (4211ba8d);
  • Failure chain: server without Range support (ignores Range, always returns 200 full) -> 10MB partial resume -> curl: (33) HTTP server does not seem to support byte ranges. Cannot resume. (exit 33), same as packer#136;
  • Trivia check: python3 -m http.server (3.14.4) also reports 33 to -C - - new versions of http.server don't support Range; don't use it for local debugging;
  • Probe method verified: curl -sI -H "Range: bytes=0-99" returns 206 for the self-written server and 200 for norange/http.server.

Evidence details kept locally (2026-08-29)

Applicable tools (1)

This problem is linked from the tool pages below — reachable from either side.

curl

Source & evidence

Recorded Verified ✓ VerifiedApplies to 1 tool(s)
Entries contain locally measured or reviewable-source solutions; unmeasured items are explicitly labeled.

Source: https://github.com/hashicorp/packer/issues/136

← Coding Agents & Terminal domain | Problem Catalog Experience | Facing another issue? Go to the Helpdesk