Hi everyone,
my Streamlit app (https://pv-dc-electrolysis.streamlit.app/) started failing on Streamlit Cloud when fetching PVGIS data via pvlib.iotools.get_pvgis_hourly. The request dies before connecting with a DNS error for re.jrc.ec.europa.eu. The same code works fine locally and used to work on Cloud until recently.
Here is the full error:
───────────────────── Traceback (most recent call last) ───────────────────────
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/connection.py:198
in _new_conn
195 │ │ :return: New socket connection.
196 │ │ """
197 │ │ try:
❱ 198 │ │ │ sock = connection.create_connection(
199 │ │ │ │ (self._dns_host, self.port),
200 │ │ │ │ self.timeout,
201 │ │ │ │ source_address=self.source_address,
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/util/connection.py
:60 in create_connection
57 │ except UnicodeError:
58 │ │ raise LocationParseError(f"'{host}', label empty or too long")
59 │
❱ 60 │ for res in socket.getaddrinfo(host, port, family, socket.SOCK_STRE
61 │ │ af, socktype, proto, canonname, sa = res
62 │ │ sock = None
63 │ │ try:
/usr/local/lib/python3.13/socket.py:977 in getaddrinfo
974 │ # We override this function since we want to translate the numeric
975 │ # and socket type values to enum constants.
976 │ addrlist = []
❱ 977 │ for res in _socket.getaddrinfo(host, port, family, type, proto, fl
978 │ │ af, socktype, proto, canonname, sa = res
979 │ │ addrlist.append((_intenum_converter(af, AddressFamily),
980 │ │ │ │ │ │ _intenum_converter(socktype, SocketKind),
────────────────────────────────────────────────────────────────────────────────
gaierror: [Errno -5] No address associated with hostname
The above exception was the direct cause of the following exception:
────────────────────── Traceback (most recent call last) ───────────────────────
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/connectionpool.py:
787 in urlopen
784 │ │ │ response_conn = conn if not release_conn else None
785 │ │ │
786 │ │ │ # Make the request on the HTTPConnection object
❱ 787 │ │ │ response = self._make_request(
788 │ │ │ │ conn,
789 │ │ │ │ method,
790 │ │ │ │ url,
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/connectionpool.py:
488 in _make_request
485 │ │ │ │ new_e, (OSError, NewConnectionError, TimeoutError, SS
486 │ │ │ ) and (conn and conn.proxy and not conn.has_connected_to_
487 │ │ │ │ new_e = _wrap_proxy_error(new_e, conn.proxy.scheme)
❱ 488 │ │ │ raise new_e
489 │ │
490 │ │ # conn.request() calls http.client.*.request, not the method
491 │ │ # urllib3.request. It also calls makefile (recv) on the socke
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/connectionpool.py:
464 in _make_request
461 │ │ try:
462 │ │ │ # Trigger any extra validation we need to do.
463 │ │ │ try:
❱ 464 │ │ │ │ self._validate_conn(conn)
465 │ │ │ except (SocketTimeout, BaseSSLError) as e:
466 │ │ │ │ self._raise_timeout(err=e, url=url, timeout_value=con
467 │ │ │ │ raise
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/connectionpool.py:
1093 in _validate_conn
1090 │ │
1091 │ │ # Force connect early to allow us to validate the connection.
1092 │ │ if conn.is_closed:
❱ 1093 │ │ │ conn.connect()
1094 │ │
1095 │ │ # TODO revise this, see https://github.com/urllib3/urllib3/is
1096 │ │ if not conn.is_verified and not conn.proxy_is_verified:
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/connection.py:753
in connect
750 │ │
751 │ │ try:
752 │ │ │ sock: socket.socket | ssl.SSLSocket
❱ 753 │ │ │ self.sock = sock = self._new_conn()
754 │ │ │ server_hostname: str = self.host
755 │ │ │ tls_in_tls = False
756
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/connection.py:205
in _new_conn
202 │ │ │ │ socket_options=self.socket_options,
203 │ │ │ )
204 │ │ except socket.gaierror as e:
❱ 205 │ │ │ raise NameResolutionError(self.host, self, e) from e
206 │ │ except SocketTimeout as e:
207 │ │ │ raise ConnectTimeoutError(
208 │ │ │ │ self,
────────────────────────────────────────────────────────────────────────────────
NameResolutionError: <urllib3.connection.HTTPSConnection object at
0x7d622def0c20>: Failed to resolve 're.jrc.ec.europa.eu' ([Errno -5] No address
associated with hostname)
The above exception was the direct cause of the following exception:
────────────────────── Traceback (most recent call last) ───────────────────────
/home/adminuser/venv/lib/python3.13/site-packages/requests/adapters.py:644
in send
641 │ │ │ timeout = TimeoutSauce(connect=timeout, read=timeout)
642 │ │
643 │ │ try:
❱ 644 │ │ │ resp = conn.urlopen(
645 │ │ │ │ method=request.method,
646 │ │ │ │ url=url,
647 │ │ │ │ body=request.body,
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/connectionpool.py:
841 in urlopen
838 │ │ │ elif isinstance(new_e, (OSError, HTTPException)):
839 │ │ │ │ new_e = ProtocolError("Connection aborted.", new_e)
840 │ │ │
❱ 841 │ │ │ retries = retries.increment(
842 │ │ │ │ method, url, error=new_e, _pool=self, _stacktrace=sys
843 │ │ │ )
844 │ │ │ retries.sleep()
/home/adminuser/venv/lib/python3.13/site-packages/urllib3/util/retry.py:519
in increment
516 │ │
517 │ │ if new_retry.is_exhausted():
518 │ │ │ reason = error or ResponseError(cause)
❱ 519 │ │ │ raise MaxRetryError(_pool, url, reason) from reason # typ
520 │ │
521 │ │ log.debug("Incremented Retry for (url='%s'): %r", url, new_ret
522
────────────────────────────────────────────────────────────────────────────────
MaxRetryError: HTTPSConnectionPool(host='re.jrc.ec.europa.eu', port=443): Max
retries exceeded with url:
/api/v5_3/seriescalc?lat=37.3891&lon=-5.9845&outputformat=json&angle=0.0&aspect=
0.0&pvcalculation=0&pvtechchoice=crystSi&mountingplace=free&trackingtype=0&compo
nents=1&usehorizon=1&optimalangles=0&optimalinclination=0&loss=0&startyear=2023&
endyear=2023 (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection
object at 0x7d622def0c20>: Failed to resolve 're.jrc.ec.europa.eu' ([Errno -5]
No address associated with hostname)"))
During handling of the above exception, another exception occurred:
────────────────────── Traceback (most recent call last) ───────────────────────
/home/adminuser/venv/lib/python3.13/site-packages/streamlit/runtime/scriptru
nner/exec_code.py:128 in exec_func_with_error_handling
/home/adminuser/venv/lib/python3.13/site-packages/streamlit/runtime/scriptru
nner/script_runner.py:669 in code_to_exec
/mount/src/pv-array---dc-direct-coupling---electrolyzer-array/app.py:322 in
<module>
319
320 # Fetch (cached unless site/year/tilt/azimuth change)
321 with st.spinner("Fetching PVGIS data and computing effective irradian
❱ 322 │ data, meta, E_eff_base = fetch_pvgis_and_effective_irradiance(
323 │ │ SITE_LAT, SITE_LON, SITE_ALT, SITE_TZ, year, SURFACE_TILT, SU
324 │ )
325
/home/adminuser/venv/lib/python3.13/site-packages/streamlit/runtime/caching/
cache_utils.py:227 in __call__
/home/adminuser/venv/lib/python3.13/site-packages/streamlit/runtime/caching/
cache_utils.py:269 in _get_or_create_cached_value
/home/adminuser/venv/lib/python3.13/site-packages/streamlit/runtime/caching/
cache_utils.py:328 in _handle_cache_miss
/mount/src/pv-array---dc-direct-coupling---electrolyzer-array/app.py:295 in
fetch_pvgis_and_effective_irradiance
292 │ SITE_LAT = SITE_LAT_local; SITE_LON = SITE_LON_local; SITE_ALT =
293 │ SURFACE_TILT = SURFACE_TILT_local; SURFACE_AZIMUTH = SURFACE_AZIM
294 │
❱ 295 │ data, meta = iotools.get_pvgis_hourly(
296 │ │ latitude=SITE_LAT, longitude=SITE_LON,
297 │ │ surface_tilt=SURFACE_TILT, surface_azimuth=SURFACE_AZIMUTH,
298 │ │ start=START, end=END,
/home/adminuser/venv/lib/python3.13/site-packages/pvlib/iotools/pvgis.py:231
in get_pvgis_hourly
228 │ │ params['peakpower'] = peakpower
229 │
230 │ # The url endpoint for hourly radiation is 'seriescalc'
❱ 231 │ res = requests.get(url + 'seriescalc', params=params, timeout=time
232 │ # PVGIS returns really well formatted error messages in JSON for H
233 │ # 400 BAD REQUEST so try to return that if possible, otherwise rai
234 │ # HTTP/1.1 error caught by requests
/home/adminuser/venv/lib/python3.13/site-packages/requests/api.py:73 in get
70 │ :rtype: requests.Response
71 │ """
72 │
❱ 73 │ return request("get", url, params=params, **kwargs)
74
75
76 def options(url, **kwargs):
/home/adminuser/venv/lib/python3.13/site-packages/requests/api.py:59 in
request
56 │ # avoid leaving sockets open which can trigger a ResourceWarning i
57 │ # cases, and look like a memory leak in others.
58 │ with sessions.Session() as session:
❱ 59 │ │ return session.request(method=method, url=url, **kwargs)
60
61
62 def get(url, params=None, **kwargs):
/home/adminuser/venv/lib/python3.13/site-packages/requests/sessions.py:589
in request
586 │ │ │ "allow_redirects": allow_redirects,
587 │ │ }
588 │ │ send_kwargs.update(settings)
❱ 589 │ │ resp = self.send(prep, **send_kwargs)
590 │ │
591 │ │ return resp
592
/home/adminuser/venv/lib/python3.13/site-packages/requests/sessions.py:703
in send
700 │ │ start = preferred_clock()
701 │ │
702 │ │ # Send the request
❱ 703 │ │ r = adapter.send(request, **kwargs)
704 │ │
705 │ │ # Total elapsed time of the request (approximately)
706 │ │ elapsed = preferred_clock() - start
/home/adminuser/venv/lib/python3.13/site-packages/requests/adapters.py:677
in send
674 │ │ │ │ # This branch is for urllib3 v1.22 and later.
675 │ │ │ │ raise SSLError(e, request=request)
676 │ │ │
❱ 677 │ │ │ raise ConnectionError(e, request=request)
678 │ │
679 │ │ except ClosedPoolError as e:
680 │ │ │ raise ConnectionError(e, request=request)
────────────────────────────────────────────────────────────────────────────────
ConnectionError: HTTPSConnectionPool(host='re.jrc.ec.europa.eu', port=443): Max
retries exceeded with url:
/api/v5_3/seriescalc?lat=37.3891&lon=-5.9845&outputformat=json&angle=0.0&aspect=
0.0&pvcalculation=0&pvtechchoice=crystSi&mountingplace=free&trackingtype=0&compo
nents=1&usehorizon=1&optimalangles=0&optimalinclination=0&loss=0&startyear=2023&
endyear=2023 (Caused by NameResolutionError("<urllib3.connection.HTTPSConnection
object at 0x7d622def0c20>: Failed to resolve 're.jrc.ec.europa.eu' ([Errno -5]
No address associated with hostname)"))
Here is the link to the GitHub repository: GitHub - TobiasFranzBRB/PV-array---DC-direct-coupling---Electrolyzer-array
Environment
-
Streamlit Cloud
-
Python 3.13
-
pvlib+requests -
Endpoint:
https://re.jrc.ec.europa.eu/api/v5_3/seriescalc
Observations
-
Works locally (no DNS issues).
-
Recently began failing on Streamlit Cloud only.
-
Looks like an outbound DNS/egress issue (failure occurs during hostname resolution, before TLS connect).
Many thanks in advance!