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
2025-01-28 15:11:42,725 - DEBUG - Starting call to '<unknown>', this is the 72232nd time calling it.
2025-01-28 15:11:42,725 - DEBUG - Starting call to '<unknown>', this is the 72233rd time calling it.
2025-01-28 15:11:42,725 - DEBUG - Starting call to '<unknown>', this is the 72234th time calling it.
2025-01-28 15:11:42,725 - DEBUG - Starting call to '<unknown>', this is the 72235th time calling it.
2025-01-28 15:11:42,725 - DEBUG - Starting call to '<unknown>', this is the 72236th time calling it.
2025-01-28 15:11:42,725 - DEBUG - Starting call to '<unknown>', this is the 72237th time calling it.
This is because retry_state.fn is probably not being set here.
fn=None because there's no wrapped function — the user's code lives in the with attempt: block. Consequently, get_fn_name() falls through to:
returnstr(self.retry_object) # → self._name or "<unknown>"
When no name= argument was passed to Retrying(...), self._name is None and __str__ returns "<unknown>". The comment # NOTE(sileht): can't really happen was valid only for the decorator path; it has been removed in the current codebase, but the underlying issue (unhelpful log output) remained.
Fix (PR linked above)
Inside __iter__, before the first yield, sys._getframe(1) refers to the frame that called next() on the generator — which is the for loop in the user's code. We capture f_code.co_qualname (Python ≥ 3.11) or f_code.co_name (older) and store it as retry_state._inferred_name.
get_fn_name() checks _inferred_name before falling back to "<unknown>", so before_log() now logs the actual enclosing function name:
# Before fix:
Starting call to '<unknown>', this is the 1st time calling it.
# After fix:
Starting call to 'my_module.my_function', this is the 1st time calling it.
Users who already pass name="my_name" are completely unaffected — that path is checked first.
Activity
LotfiRafik commentedon Feb 16, 2025
This comment "# NOTE(sileht): can't really happen, but we must please mypy" is outdated. retry_state.fn can be None in the case of using retry inside context manager. its the expected behaviour not a bug.
Mukller commentedon Jul 30, 2026
Root cause analysis
When
Retryingis used as a context manager (thefor attempt in Retrying(...): with attempt:pattern),__iter__creates:fn=Nonebecause there's no wrapped function — the user's code lives in thewith attempt:block. Consequently,get_fn_name()falls through to:When no
name=argument was passed toRetrying(...),self._nameisNoneand__str__returns"<unknown>". The comment# NOTE(sileht): can't really happenwas valid only for the decorator path; it has been removed in the current codebase, but the underlying issue (unhelpful log output) remained.Fix (PR linked above)
Inside
__iter__, before the firstyield,sys._getframe(1)refers to the frame that callednext()on the generator — which is theforloop in the user's code. We capturef_code.co_qualname(Python ≥ 3.11) orf_code.co_name(older) and store it asretry_state._inferred_name.get_fn_name()checks_inferred_namebefore falling back to"<unknown>", sobefore_log()now logs the actual enclosing function name:Users who already pass
name="my_name"are completely unaffected — that path is checked first.