Skip to content

fix: include Zenodo API error response body in error messages (#169)#181

Open
rtmalikian wants to merge 2 commits into
BrainLesion:mainfrom
rtmalikian:fix/zenodo-error-response-display
Open

fix: include Zenodo API error response body in error messages (#169)#181
rtmalikian wants to merge 2 commits into
BrainLesion:mainfrom
rtmalikian:fix/zenodo-error-response-display

Conversation

@rtmalikian

Copy link
Copy Markdown

Summary

When the Zenodo API returns a non-200 status code, the error response body (which contains the actual explanation from Zenodo) was being discarded. The error message only showed the status code, making it impossible to diagnose issues like rate limiting (429), access denied (403), or invalid records (404).

What was broken

In _get_metadata_and_archive_url(), the error message was:

Cannot find record '15236131' on Zenodo (response.status_code=403).

This provided no information about why the request failed. Users had no way to distinguish between rate limiting, access restrictions, or invalid record IDs without manually visiting the URL in a browser.

What the fix does

  1. Parses the response body — attempts JSON first (Zenodo returns structured error responses), falls back to raw text if the response isn't valid JSON.
  2. Includes the error detail in the exception message — users now see the full context, e.g.:
    Cannot find record '15236131' on Zenodo (status_code=403). Response: {'message': 'Rate limit exceeded', 'status': 403}
    
  3. Updated tests — the existing 404 test now verifies the response body is included, and a new test covers the non-JSON fallback path.

Fixes #169

Verification

All 13 tests pass:

tests/test_zenodo.py::test_get_metadata_and_archive_url_success PASSED
tests/test_zenodo.py::test_get_metadata_and_archive_url_failure PASSED
tests/test_zenodo.py::test_get_metadata_and_archive_url_failure_with_text_body PASSED
tests/test_zenodo.py::test_get_metadata_and_archive_url_connection_error PASSED
tests/test_zenodo.py::test_get_latest_version_folder_name PASSED
tests/test_zenodo.py::test_get_latest_version_folder_name_empty PASSED
tests/test_zenodo.py::test_get_latest_version_folder_name_ignores_empty_folder PASSED
tests/test_zenodo.py::test_fetch_downloads_new_if_no_local PASSED
tests/test_zenodo.py::test_fetch_zenodo_unreachable_raises PASSED
tests/test_zenodo.py::test_fetch_skips_if_latest_present PASSED
tests/test_zenodo.py::test_fetch_replaces_old_version PASSED
tests/test_zenodo.py::test_fetch_atlases_calls_fetch PASSED
tests/test_zenodo.py::test_fetch_synthstrip_calls_fetch PASSED

======================== 13 passed ========================

About the Author: Raphael Malikian — Clinical AI Solutions Architect. I specialise in building and fixing AI/ML systems for healthcare, including vector databases, RAG pipelines, and clinical NLP. If you need help with your project or think I can add value to your organisation, feel free to reach out — I'd love to connect.

📧 rtmalikian@gmail.com
🔗 GitHub: https://github.com/rtmalikian
🔗 LinkedIn: http://www.linkedin.com/in/raphael-t-malikian-mbbs-bsc-hons-71075436a


Disclosure: This code was developed with assistance from mimo-2.5-pro (Xiaomi) via Hermes Agent (Nous Research). All changes were reviewed, tested against the actual codebase, and verified for correctness.

When a non-200 status code is returned from the Zenodo API, the error
message now includes the response body (JSON or text) so users can
diagnose the root cause (e.g., rate limiting, access denied, invalid
record).

Previously, only the status code was shown, making it impossible to
debug intermittent 403/429 errors without using a browser.

Fixes BrainLesion#169
@neuronflow neuronflow requested review from MarcelRosier and Copilot and removed request for Copilot June 18, 2026 11:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves diagnosability of Zenodo download failures by surfacing Zenodo’s error response body in the raised ZenodoException, and extends test coverage to validate both JSON and plain-text error bodies.

Changes:

  • Include Zenodo error response content (JSON or text fallback) in _get_metadata_and_archive_url() exception messages.
  • Update the existing failure test to assert that JSON error details appear in the exception message.
  • Add a new test covering the non-JSON (text body) fallback path.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
brainles_preprocessing/utils/zenodo.py Adds parsing of Zenodo error bodies and includes them in the raised exception message.
tests/test_zenodo.py Expands assertions for error messages and adds a text-body fallback test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +142 to +145
try:
error_detail = response.json()
except (ValueError, requests.exceptions.JSONDecodeError):
error_detail = response.text.strip()
Comment on lines 147 to 151
error_msg = (
f"Cannot find record '{self.record_id}' on Zenodo "
f"({response.status_code=})."
f"(status_code={response.status_code}). "
f"Response: {error_detail}"
)
1. Catch ValueError only (requests.exceptions.JSONDecodeError is a
   subclass and may not exist in older requests versions)
2. Use status-code-aware error messages: 'Cannot find record' for 404,
   'Failed to fetch record' for other status codes (403, 429, etc.)
@rtmalikian

Copy link
Copy Markdown
Author

Hi, I've addressed both Copilot review comments:

  1. ** portability (line 144):** Changed to catch only — is a subclass of and is guaranteed to be caught, while itself may not exist in older versions.

  2. Status-code-aware error messages (line 148): Changed from the generic "Cannot find record" to:

    • 404 → "Cannot find record" (record genuinely doesn't exist)
    • Other codes (403, 429, 500, etc.) → "Failed to fetch record" (more accurate for permission/rate-limit/server errors)

All 13 tests pass with the updated code. PR is ready for re-review. 🙏

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.

[BUG] Zenodo api error response not saved nor displayed

2 participants