[PR #15028] fix: prevent digest mismatch on blob downloads #40848

Open
opened 2026-04-23 01:38:53 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/ollama/ollama/pull/15028
Author: @hubsmoke
Created: 3/23/2026
Status: 🔄 Open

Base: mainHead: fix/digest-mismatch-download-corruption


📝 Commits (1)

  • c4d803c fix: prevent digest mismatch on blob downloads

📊 Changes

3 files changed (+166 additions, -2 deletions)

View changed files

📝 server/download.go (+35 -0)
server/download_test.go (+120 -0)
📝 server/images.go (+11 -2)

📄 Description

Summary

Fixes the long-standing "digest mismatch, file must be downloaded again" error that affects model pulls, especially large models (40GB+). This has been an open issue since October 2023.

Root causes addressed:

  • Missing HTTP status validation in downloadChunk — non-206/200 responses (expired CDN URLs returning 403, error pages, bad gateway responses) were silently written into the blob file, corrupting it. This is the most likely primary cause for large models where CDN redirect URLs can expire mid-transfer.
  • No pre-rename digest verification — the assembled partial file was renamed to the final blob path without hash verification, and corrupted partial data was reused on retry instead of starting fresh.
  • No automatic retry — users had to manually rm -rf blobs and re-pull after every mismatch.

Changes:

  • server/download.go: Validate HTTP response status code (206/200) before writing chunk data. Verify SHA256 digest of assembled file before renaming from -partial to final blob path. On mismatch, clean up all partial + part tracking files so retries start fresh.
  • server/images.go: Auto-retry download once on digest mismatch in PullModel, since cleanup ensures a fresh start.
  • server/download_test.go: Tests for digest verification and HTTP status rejection.

Testing

  • All existing server tests pass (389 tests, 0 failures)
  • New tests: TestVerifyBlobFile (3 cases) and TestDownloadChunkRejectsNon206 (5 cases) pass
  • Verified with all-minilm (45MB) — pull + verify succeeds
  • Verified with qwen2.5:72b (47GB) — pull + verify succeeds, including recovery from a TLS error (tls: bad record MAC) on one part during download

Test plan

  • Pull a small model and verify success
  • Pull a large model (40GB+) and verify no digest mismatch
  • Simulate a failed/corrupted partial download and verify retry starts fresh
  • Verify non-206 HTTP responses are rejected and retried

Fixes #941, #3326, #3931, #8105, #9846, #11831, #13775, #14554


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/ollama/ollama/pull/15028 **Author:** [@hubsmoke](https://github.com/hubsmoke) **Created:** 3/23/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/digest-mismatch-download-corruption` --- ### 📝 Commits (1) - [`c4d803c`](https://github.com/ollama/ollama/commit/c4d803cf7472dd2eceb3956f76351ae1ca4bbf48) fix: prevent digest mismatch on blob downloads ### 📊 Changes **3 files changed** (+166 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `server/download.go` (+35 -0) ➕ `server/download_test.go` (+120 -0) 📝 `server/images.go` (+11 -2) </details> ### 📄 Description ## Summary Fixes the long-standing "digest mismatch, file must be downloaded again" error that affects model pulls, especially large models (40GB+). This has been an open issue since October 2023. **Root causes addressed:** - **Missing HTTP status validation in `downloadChunk`** — non-206/200 responses (expired CDN URLs returning 403, error pages, bad gateway responses) were silently written into the blob file, corrupting it. This is the most likely primary cause for large models where CDN redirect URLs can expire mid-transfer. - **No pre-rename digest verification** — the assembled partial file was renamed to the final blob path without hash verification, and corrupted partial data was reused on retry instead of starting fresh. - **No automatic retry** — users had to manually `rm -rf` blobs and re-pull after every mismatch. **Changes:** - **`server/download.go`**: Validate HTTP response status code (206/200) before writing chunk data. Verify SHA256 digest of assembled file before renaming from `-partial` to final blob path. On mismatch, clean up all partial + part tracking files so retries start fresh. - **`server/images.go`**: Auto-retry download once on digest mismatch in `PullModel`, since cleanup ensures a fresh start. - **`server/download_test.go`**: Tests for digest verification and HTTP status rejection. ## Testing - All existing server tests pass (389 tests, 0 failures) - New tests: `TestVerifyBlobFile` (3 cases) and `TestDownloadChunkRejectsNon206` (5 cases) pass - Verified with `all-minilm` (45MB) — pull + verify succeeds - Verified with `qwen2.5:72b` (47GB) — pull + verify succeeds, including recovery from a TLS error (`tls: bad record MAC`) on one part during download ## Test plan - [ ] Pull a small model and verify success - [ ] Pull a large model (40GB+) and verify no digest mismatch - [ ] Simulate a failed/corrupted partial download and verify retry starts fresh - [ ] Verify non-206 HTTP responses are rejected and retried Fixes #941, #3326, #3931, #8105, #9846, #11831, #13775, #14554 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-23 01:38:53 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/ollama#40848