Skip to content

fix: correct exception handling in get_external_ip fallback chain#3311

Open
Grizouforever wants to merge 2 commits intolatent-to:masterfrom
Grizouforever:fix/external-ip-exception-handling
Open

fix: correct exception handling in get_external_ip fallback chain#3311
Grizouforever wants to merge 2 commits intolatent-to:masterfrom
Grizouforever:fix/external-ip-exception-handling

Conversation

@Grizouforever
Copy link
Copy Markdown

Summary

Fixes #3309

The fallback chain in get_external_ip() catches ExternalIPNotFound, but none of the code inside the try blocks actually raises that exception. Real exceptions (requests.RequestException, AssertionError, OSError, json.JSONDecodeError, etc.) propagate unhandled, preventing fallthrough to the next IP provider. This means if the first provider (AWS checkip) fails, the function crashes instead of trying the remaining 5 providers.

Changes

bittensor/utils/networking.py:

  • Replace all except ExternalIPNotFound with except Exception to properly catch real exceptions
  • Replace deprecated os.popen() calls with subprocess.run() (Python 3.0+ recommended)
  • Replace bare assert isinstance(...) validation with direct ip_to_int() calls that raise on invalid input regardless of -O optimization flag

Context

PR #3262 previously attempted this fix but was closed due to being based on the wrong branch and author not responding to review. This PR is based on master (the current default branch) and incorporates the additional improvements suggested.

Test User and others added 2 commits April 11, 2026 13:32
The fallback chain in get_external_ip() catches ExternalIPNotFound
but none of the code inside the try blocks raises that exception.
The actual exceptions (requests.RequestException, AssertionError,
OSError, json.JSONDecodeError, etc.) propagate unhandled, preventing
fallthrough to the next IP provider.

Changes:
- Replace all `except ExternalIPNotFound` with `except Exception`
  to properly catch real exceptions and allow fallthrough
- Replace deprecated `os.popen()` calls with `subprocess.run()`
- Replace bare `assert` validation with direct `ip_to_int()` calls
  which raise on invalid input regardless of -O flag

Fixes latent-to#3309
The implementation in bittensor/utils/networking.py was updated in this
PR to replace os.popen("curl ...") with subprocess.run(...), but the
test test_get_external_ip_os_request_urllib_broken still mocked os.popen
which no longer intercepts any calls. Update the test to mock
subprocess.run and bittensor.utils.networking.urllib_request.urlopen so
all fallback paths are properly blocked and the expected ExternalIPNotFound
exception is raised.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@thewhaleking thewhaleking requested a review from a team April 14, 2026 10:19
@thewhaleking
Copy link
Copy Markdown
Contributor

Read CONTRIBUTING

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.

get_external_ip fallback chain never triggers — all attempts catch ExternalIPNotFound but none of the called functions raise it

2 participants