Raise dedicated HashValidationError on download/extract hash mismatch#9001
Raise dedicated HashValidationError on download/extract hash mismatch#9001vishnukannaujia wants to merge 1 commit into
Conversation
Fixes Project-MONAI#8832. Hash-validation failures in download_url and extractall previously raised a plain RuntimeError whose message contains "md5 check". The test helper skip_if_downloading_fails matched that substring and turned genuine hash mismatches (data corruption / content mismatch) into skipped tests, hiding real failures behind the same path as transient network errors. Introduce HashValidationError(RuntimeError) and raise it at all three hash checks (existing file, downloaded file, compressed file). Subclassing RuntimeError keeps existing `except RuntimeError` handlers working and the message text unchanged. skip_if_downloading_fails now re-raises HashValidationError instead of skipping, and the now-redundant "md5 check" entry is removed from DOWNLOAD_FAIL_MSGS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Vishnu Kannaujia <vishnu.kannaujia@gmail.com>
📝 WalkthroughWalkthroughAdds and exports Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
monai/apps/utils.py (2)
45-53: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSort
__all__alphabetically.Sort the exports to improve readability.
♻️ Proposed refactor
__all__ = [ + "HashValidationError", + "SUPPORTED_HASH_TYPES", "check_hash", + "download_and_extract", "download_url", "extractall", - "download_and_extract", "get_logger", - "SUPPORTED_HASH_TYPES", - "HashValidationError", ]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@monai/apps/utils.py` around lines 45 - 53, Sort the entries in __all__ alphabetically, including check_hash, download_url, extractall, download_and_extract, get_logger, SUPPORTED_HASH_TYPES, and HashValidationError.Source: Linters/SAST tools
235-242: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsolidate duplicate docstring entries.
HashValidationErroris listed twice in theRaisessection. Combine the descriptions into a single entry. As per path instructions, ensure definitions describe each raised exception appropriately in the Google-style format.♻️ Proposed refactor
Raises: - HashValidationError: When the hash validation of the ``filepath`` existing file fails. + HashValidationError: When the hash validation of the ``filepath`` existing file or the ``url`` downloaded file fails. RuntimeError: When a network issue or denied permission prevents the file download from ``url`` to ``filepath``. URLError: See urllib.request.urlretrieve. HTTPError: See urllib.request.urlretrieve. ContentTooShortError: See urllib.request.urlretrieve. IOError: See urllib.request.urlretrieve. - HashValidationError: When the hash validation of the ``url`` downloaded file fails.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@monai/apps/utils.py` around lines 235 - 242, Consolidate the duplicate HashValidationError entries in the Raises section of the relevant download function’s docstring into one Google-style entry that covers both existing-file and downloaded-file hash validation failures, while preserving the other exception descriptions.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@monai/apps/utils.py`:
- Around line 45-53: Sort the entries in __all__ alphabetically, including
check_hash, download_url, extractall, download_and_extract, get_logger,
SUPPORTED_HASH_TYPES, and HashValidationError.
- Around line 235-242: Consolidate the duplicate HashValidationError entries in
the Raises section of the relevant download function’s docstring into one
Google-style entry that covers both existing-file and downloaded-file hash
validation failures, while preserving the other exception descriptions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d0887511-0050-43e0-984a-a6a0b4b95f42
📒 Files selected for processing (3)
monai/apps/utils.pytests/apps/test_download_and_extract.pytests/test_utils.py
Fixes #8832.
Summary
Follow-up to the note left in #8699: a hash-validation failure should raise something specific so it is not silently suppressed by
skip_if_downloading_fails.Today
download_urlandextractallraise a plainRuntimeErroron a hash mismatch, with a message containing"md5 check". The test helperskip_if_downloading_fails(tests/test_utils.py) matches that substring inDOWNLOAD_FAIL_MSGSand converts the failure into a skipped test — the same treatment as transient network errors. As a result a genuine hash mismatch (data corruption, or the remote content having changed) is quietly skipped instead of surfaced.Changes
HashValidationError(RuntimeError)inmonai/apps/utils.py(exported in__all__). It is a subclass ofRuntimeError, so existingexcept RuntimeErrorhandlers keep working and no message text changes.HashValidationErrorat all three hash checks: existing file and downloaded file (download_url), and compressed file (extractall). DocstringRaises:entries updated accordingly.skip_if_downloading_failsnow re-raisesHashValidationError(before the genericRuntimeErrorhandling) instead of skipping."md5 check"entry fromDOWNLOAD_FAIL_MSGS— hash failures are represented by the dedicated type, and this entry would otherwise still swallow them.Backward compatibility
HashValidationErrorsubclassesRuntimeError; callers catchingRuntimeErrorare unaffected.str(e).startswith("md5 check")intest_download_and_extract.pystill hold.Tests
New offline tests (no network required) in
tests/apps/test_download_and_extract.py:HashValidationError;extractallwith a wrong hash →HashValidationError;HashValidationErroris aRuntimeErrorsubclass;skip_if_downloading_failspropagatesHashValidationErrorrather than skipping.Note for reviewers
Removing
"md5 check"fromDOWNLOAD_FAIL_MSGSis a deliberate behavior change: a fully-downloaded file whose hash does not match will now fail rather than skip. This is the intent of #8832 (distinguishing corruption from transient/incomplete downloads, which still surface as"unexpected EOF"/"network issue"). Happy to adjust if maintainers prefer to keep skipping in a specific CI path.