Skip to content

fix: fallback to backup API when geojs returns empty region#1103

Closed
ucodia wants to merge 2 commits intomlco2:masterfrom
ucodia:master
Closed

fix: fallback to backup API when geojs returns empty region#1103
ucodia wants to merge 2 commits intomlco2:masterfrom
ucodia:master

Conversation

@ucodia
Copy link
Contributor

@ucodia ucodia commented Mar 13, 2026

Description

Updated GeoMetadata.from_geo_js() to handle responses where the geojs API returns a successful HTTP 200 response but with an empty region field. When this happens, it now logs a warning and falls through to the existing ip-api.com backup chain instead of returning incomplete metadata.

Related Issue

Resolves #1101

Motivation and Context

For certain IP ranges, get.geojs.io returns a successful lookup but with no region field. Because no exception was raised, from_geo_js() previously returned this incomplete data immediately. Downstream, this caused get_region_emissions() to perform lookups with an empty string, triggering KeyError: '' and falling back to country-level emissions with incorrect geographic coordinates logged.

How Has This Been Tested?

  • Added GEO_METADATA_CANADA_EMPTY_REGION test fixtures in tests/testdata.py.
  • Added a new unit test test_geo_metadata_empty_region_falls_back_to_backup in to verify that an empty region correctly triggers the fallback.
  • Ran uv run pytest tests/test_geography.py -v successfully.
  • Verified that all other existing test cases continue to pass unaffected.

Screenshots (if appropriate):

N/A

Types of changes

What types of changes does your code introduce? Put an x in all the boxes that apply:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

Go over all the following points, and put an x in all the boxes that apply.

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING.md document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@ucodia ucodia requested a review from a team as a code owner March 13, 2026 05:58
Copy link
Contributor

@benoit-cty benoit-cty left a comment

Choose a reason for hiding this comment

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

Thanks Lionel for improving CodeCarbon !

@codecov
Copy link

codecov bot commented Mar 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.23%. Comparing base (2282658) to head (c0a842a).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1103      +/-   ##
==========================================
+ Coverage   78.22%   78.23%   +0.01%     
==========================================
  Files          38       38              
  Lines        3632     3634       +2     
==========================================
+ Hits         2841     2843       +2     
  Misses        791      791              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ucodia
Copy link
Contributor Author

ucodia commented Mar 13, 2026

@benoit-cty after testing this in my production environment I discovered a few issues with the existing fallback mechanism.

Issue 1

The fallback API will always fail when using the HTTPS endpoint

curl https://ip-api.com/json/
{"status":"fail","message":"SSL unavailable for this endpoint, order a key at https://members.ip-api.com/"}%

Using the HTTP endpoint is not great because this could expose the application location to eavesdropper and be vulnerable to man-in-the-middle.

Issue 2

If the fallback API call fails, it reports on the wrong URL on the exception: https://github.com/ucodia/codecarbon/blob/ebc8d1a3f5dcae9013dcbe6883d05e711ad6ce28/codecarbon/external/geography.py#L136

Proposal

After doing some research I found that ipinfo.io offers compliant IP geolocation

  • Provides region information
  • HTTPS without API key
  • Allowed in commercial software

Similarly to previous fallback provider it does not provide the 3 letter country code but instead of calling yet another API, I suggest we add a dependency on pycountry. Also since this is static data that practically never changes we did not need an API for that in the first place.

If you are ok with the suggested new path, I can close this PR and open a new issue to properly track this.

@ucodia
Copy link
Contributor Author

ucodia commented Mar 14, 2026

@benoit-cty created a new PR for the proposed changes and updated the original issue with context: #1104

@ucodia ucodia closed this Mar 14, 2026
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.

Geolocation fallback provider is not working

2 participants