Skip to content

Fix #5985: Training fails on Windows app - weights cannot be download...#6022

Closed
JiwaniZakir wants to merge 1 commit intoopen-edge-platform:developfrom
JiwaniZakir:fix/5985-training-fails-on-windows-app-weights-ca
Closed

Fix #5985: Training fails on Windows app - weights cannot be download...#6022
JiwaniZakir wants to merge 1 commit intoopen-edge-platform:developfrom
JiwaniZakir:fix/5985-training-fails-on-windows-app-weights-ca

Conversation

@JiwaniZakir
Copy link
Copy Markdown

Closes #5985

Summary

Fixes SSL certificate verification failure when downloading pretrained weights on Windows. On Windows, Python's urllib does not use the system certificate store by default, causing ssl.SSLCertVerificationError: CERTIFICATE_VERIFY_FAILED when fetching weights from GitHub releases (e.g., deim_dfine_hgnetv2_m_coco_90e.pth).

The fix is in library/src/otx/backend/native/models/utils/utils.py, inside load_from_http. Before initiating the download, a custom HTTPS opener is installed using certifi's CA bundle:

ssl_ctx = ssl.create_default_context(cafile=certifi.where())
urllib.request.install_opener(urllib.request.build_opener(urllib.request.HTTPSHandler(context=ssl_ctx)))

This ensures that urllib-based downloads resolve certificate chains correctly regardless of the host OS certificate store.

Resolves #5985.

How to test

Automated: A new unit test in library/tests/unit/backend/native/models/utils/test_utils.py (test_load_from_http_uses_certifi_ssl) verifies that load_from_http calls urllib.request.install_opener with an opener constructed from certifi's CA bundle before delegating to load_url.

Manual (Windows only): On a Windows machine running Geti, create a detection project using the DEIM_D_FINE_M template, start training, and confirm it completes without CERTIFICATE_VERIFY_FAILED in the logs.

Checklist

  • The PR title and description are clear and descriptive
  • I have manually tested the changes
  • All changes are covered by automated tests
  • All related issues are linked to this PR (if applicable)
  • Documentation has been updated (if applicable)

This PR was created with AI assistance (Claude). The changes were reviewed by quality gates and a critic model before submission.

@JiwaniZakir JiwaniZakir requested a review from a team as a code owner April 1, 2026 18:04
Copilot AI review requested due to automatic review settings April 1, 2026 18:04
@github-actions github-actions bot added the TEST Any changes in tests label Apr 1, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 addresses Windows training failures caused by SSL certificate verification errors when downloading pretrained weights via urllib (e.g., from GitHub releases) by installing an HTTPS opener configured with Certifi’s CA bundle inside load_from_http.

Changes:

  • Install a custom urllib HTTPS opener using an SSLContext created with certifi.where() before downloading weights.
  • Add a unit test intended to verify that load_from_http installs an opener prior to delegating to load_url.

Reviewed changes

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

File Description
library/src/otx/backend/native/models/utils/utils.py Installs a Certifi-backed HTTPS opener before calling load_url in load_from_http.
library/tests/unit/backend/native/models/utils/test_utils.py Adds a unit test for the opener installation behavior.

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

Comment on lines +137 to +140
# Use certifi's CA bundle to fix SSL certificate verification on Windows
ssl_ctx = ssl.create_default_context(cafile=certifi.where())
urllib.request.install_opener(urllib.request.build_opener(urllib.request.HTTPSHandler(context=ssl_ctx)))

Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

urllib.request.install_opener(...) installs a global opener for the whole process. Doing this unconditionally on every load_from_http call can create hard-to-debug side effects (and potential races in multi-threaded code) and may break environments that rely on the OS trust store or a custom opener (e.g., corporate MITM roots). Consider limiting this to Windows only and/or installing once (e.g., guarded by a module-level flag/lock), and avoid overriding an existing opener if one is already configured.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +14
import ssl
import urllib.request
from unittest.mock import MagicMock, patch

import certifi
import pytest

Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

This test file has several unused imports (ssl, urllib.request, MagicMock, patch, certifi, pytest). The repo's Ruff config does not ignore F401 for tests, so this will fail linting. Please remove unused imports or use them as part of the assertions.

Suggested change
import ssl
import urllib.request
from unittest.mock import MagicMock, patch
import certifi
import pytest

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +33
mocker.patch("urllib.request.install_opener", side_effect=capture_install_opener)
mock_load_url = mocker.patch("otx.backend.native.models.utils.utils.load_url", return_value={"state_dict": {}})
mocker.patch("otx.backend.native.models.utils.utils.get_dist_info", return_value=(0, 1))

load_from_http("https://example.com/model.pth", map_location="cpu")

assert installed_opener is not None, "install_opener was not called"
mock_load_url.assert_called_once()
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The test currently only asserts that install_opener was called, but it doesn't verify the key behavior described in the PR (that the opener is built with an HTTPSHandler using an SSLContext created from certifi.where()). Strengthen the test by asserting ssl.create_default_context is called with cafile=certifi.where() and/or that urllib.request.HTTPSHandler receives that context, otherwise the test could pass even if certifi isn't actually used.

Suggested change
mocker.patch("urllib.request.install_opener", side_effect=capture_install_opener)
mock_load_url = mocker.patch("otx.backend.native.models.utils.utils.load_url", return_value={"state_dict": {}})
mocker.patch("otx.backend.native.models.utils.utils.get_dist_info", return_value=(0, 1))
load_from_http("https://example.com/model.pth", map_location="cpu")
assert installed_opener is not None, "install_opener was not called"
mock_load_url.assert_called_once()
mock_ssl_context = MagicMock(spec=ssl.SSLContext)
mock_create_default_context = mocker.patch(
"ssl.create_default_context",
return_value=mock_ssl_context,
)
mock_https_handler = mocker.patch("urllib.request.HTTPSHandler")
mocker.patch("urllib.request.install_opener", side_effect=capture_install_opener)
mock_load_url = mocker.patch(
"otx.backend.native.models.utils.utils.load_url",
return_value={"state_dict": {}},
)
mocker.patch("otx.backend.native.models.utils.utils.get_dist_info", return_value=(0, 1))
load_from_http("https://example.com/model.pth", map_location="cpu")
# Ensure an opener was installed (existing behavior).
assert installed_opener is not None, "install_opener was not called"
mock_load_url.assert_called_once()
# New assertions: certifi's CA bundle must be used to create the SSL context,
# and that context must be passed to HTTPSHandler.
mock_create_default_context.assert_called_once_with(cafile=certifi.where())
mock_https_handler.assert_called_once_with(context=mock_ssl_context)

Copilot uses AI. Check for mistakes.
@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@leoll2 leoll2 closed this Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

TEST Any changes in tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Training fails on Windows app - weights cannot be download when using

4 participants