The ModelScope file endpoint answers a Range request with 200 OK instead of 206 Partial Content, even though it does serve only the requested slice:
curl -sL -o /dev/null -D -
-H 'Range: bytes=1000000000-1000000099'
'https://www.modelscope.cn/api/v1/models/Qwen/Qwen3-VL-8B-Instruct/repo?Revision=master&FilePath=model-00002-of-00004.safetensors'
Returned:
HTTP/1.1 200 OK
Server: nginx/1.24.0
Content-Length: 100
Accept-Ranges: bytes
Content-Range: bytes 1000000000-1000000099/4915962496
100 bytes requested, 100 bytes returned, correct Content-Range — the range is honoured. Only the status code is wrong. Per RFC 9110 §15.3.7 this should be 206.
And it may break the SDK
_download_with_resume decides whether a response is a resume from the status code alone.
is_resumed = resp.status_code == 206
...
mode = "ab" if is_resumed else "wb"
if not is_resumed:
existing_size = 0
So on every resume is_resumed is False, and the .incomplete file is truncated (wb) — but the server is still sending from the requested offset, so mid-file bytes get written at offset 0. The result is a file that is both short and shifted. Nothing notices until the SHA-256 check rejects it, which then deletes the file and restarts from byte 0.
In one run over an unreliable link, /proc//io showed 30.9 GB written for a 17.5 GB model, with 6.1 GB retained.
The ModelScope file endpoint answers a Range request with 200 OK instead of 206 Partial Content, even though it does serve only the requested slice:
Returned:
100 bytes requested, 100 bytes returned, correct Content-Range — the range is honoured. Only the status code is wrong. Per RFC 9110 §15.3.7 this should be 206.
And it may break the SDK
_download_with_resumedecides whether a response is a resume from the status code alone.So on every resume is_resumed is False, and the .incomplete file is truncated (wb) — but the server is still sending from the requested offset, so mid-file bytes get written at offset 0. The result is a file that is both short and shifted. Nothing notices until the SHA-256 check rejects it, which then deletes the file and restarts from byte 0.
In one run over an unreliable link, /proc//io showed 30.9 GB written for a 17.5 GB model, with 6.1 GB retained.