You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Oct 6, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Oct 6, 2026. It is now read-only.
max_retries and retry_delay constructor parameters are stored but never used — retry count is hardcoded to 10 #320
max_retries and retry_delay constructor parameters are silently ignored
SDK version: 0.5.24 (also confirmed in 0.5.15) Python version: 3.12
Description
The Runware / RunwareServer constructor accepts max_retries and retry_delay parameters, which are documented and stored internally, but never actually used. Both retry loops in RunwareBase ignore them entirely and use a hardcoded constant (MAX_RETRY_ATTEMPTS = 10) instead. Setting max_retries=0 or any other value has no observable effect on runtime behaviour.
Steps to reproduce
importasynciofromrunwareimportRunware, IVideoInferenceasyncdefmain():
# Expectation: no retries. Reality: up to 10 retries will happen on ConnectionError.runware=Runware(
api_key="your-api-key",
max_retries=0,
retry_delay=0,
)
awaitrunware.connect()
# Submit any job that triggers a WebSocket drop mid-flight;# the SDK will retry up to 10 times regardless of the values above.asyncio.run(main())
The symptom we encountered: after a WebSocket drop, the SDK reconnects and resubmits the same request with the same taskUUID. The server returns a 409 conflictTaskUUID error — proving that retries did happen, despite max_retries=0.
server.py (lines 33–48): both parameters are accepted and stored, but self._max_retries and self._retry_delay are never read again anywhere in the codebase.
# server.pydef__init__(
self,
api_key: str,
max_retries: int=2, # ← stored...retry_delay: int=1, # ← stored...
):
...
self._max_retries: int=max_retries# ← ...but never usedself._retry_delay: int=retry_delay# ← ...but never used
utils.py (line 114): the actual retry count is a hardcoded module-level constant, not controllable via any constructor argument or environment variable (unlike MAX_CONCURRENT_REQUESTS, which does read from env).
# utils.pyMAX_RETRY_ATTEMPTS=10# hardcoded; no env-var override
base.py (lines 413 and 461): both _retry_with_reconnect and _retry_async_with_reconnect loop over MAX_RETRY_ATTEMPTS instead of self._max_retries, and use their own jitter/backoff logic instead of self._retry_delay.
# base.py — _retry_with_reconnect (line 413)forattemptinrange(MAX_RETRY_ATTEMPTS): # ← should be self._max_retries
...
ifreconnected:
jitter=uniform(0.1, 0.5) * (attempt+1)
awaitasyncio.sleep(jitter) # ← self._retry_delay not usedelse:
delay=self._reconnection_manager.calculate_delay()
awaitasyncio.sleep(delay) # ← self._retry_delay not used# base.py — _retry_async_with_reconnect (line 461)forattemptinrange(MAX_RETRY_ATTEMPTS): # ← same issue
...
Expected behaviour
max_retries=N should cap the number of retry attempts to N. max_retries=0 should mean no retries — a single attempt is made and any error is raised immediately to the caller.
retry_delay=N should control the sleep duration between retry attempts.
Suggested fix
In RunwareBase.__init__, accept and store the parameters (they could be passed down from RunwareServer), then use them in both retry loops:
# base.py — _retry_with_reconnectforattemptinrange(self._max_retries+1): # +1 so 0 = one attempt, no retry
...
awaitasyncio.sleep(self._retry_delay)
# base.py — _retry_async_with_reconnectforattemptinrange(self._max_retries+1):
...
awaitasyncio.sleep(self._retry_delay)
Alternatively, keep the jitter/backoff logic for the delay but at least wire self._max_retries into the loop bound.
Additional notes
retry_delay has the exact same problem: stored in RunwareServer, never referenced in RunwareBase.
MAX_RETRY_ATTEMPTS could remain as the default value when the caller does not pass max_retries, preserving backward compatibility.
Activity