Skip to content

Fix retry_if_exception_message rejecting empty string arguments#598

Open
bysiber wants to merge 1 commit intojd:mainfrom
bysiber:fix/retry-exception-message-empty-string
Open

Fix retry_if_exception_message rejecting empty string arguments#598
bysiber wants to merge 1 commit intojd:mainfrom
bysiber:fix/retry-exception-message-empty-string

Conversation

@bysiber
Copy link

@bysiber bysiber commented Feb 20, 2026

Summary

retry_if_exception_message(message="") incorrectly raises TypeError instead of creating a predicate that matches exceptions with empty string representations.

The Bug

The constructor uses Python truthiness checks (if message, elif match) instead of is not None checks. Since empty string "" is falsy:

  • message="" falls through to else and raises TypeError
  • match="" falls through to else and raises TypeError
  • message="", match="foo" silently uses match instead of raising the mutual exclusion error
from tenacity import retry_if_exception_message

# This should match exceptions like Exception() where str(Exception()) == ""
# Instead raises: TypeError: retry_if_exception_message() missing 1 required argument 'message' or 'match'
r = retry_if_exception_message(message="")

The same issue affects retry_if_not_exception_message since it inherits the constructor.

The Fix

Replaced if message / elif match with if message is not None / elif match is not None.

The truthiness checks (if message, elif match) treat empty string
as falsy, so message='' or match='' falls through to the else
branch and raises TypeError. These are valid values — an empty
message matches exceptions like Exception() where str(exc) == ''.

Switched to 'is not None' checks.
Copy link
Owner

@jd jd left a comment

Choose a reason for hiding this comment

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

The fix is correct — nice catch on the truthiness vs is not None distinction. All three conditionals are fixed consistently, and the mutual exclusion check now correctly catches message="", match="foo".

However, please add test cases to prevent regression. At minimum:

def test_retry_if_exception_message_empty_string(self):
    r = retry_if_exception_message(message="")
    # Should match Exception() since str(Exception()) == ""
    self.assertTrue(r(make_retry_state(Exception())))
    # Should not match Exception("foo")
    self.assertFalse(r(make_retry_state(Exception("foo"))))

def test_retry_if_exception_message_match_empty_string(self):
    r = retry_if_exception_message(match="")
    # Empty regex matches everything
    self.assertTrue(r(make_retry_state(Exception("anything"))))

def test_retry_if_exception_message_both_empty(self):
    with self.assertRaises(TypeError):
        retry_if_exception_message(message="", match="")

Same cases should be added for retry_if_not_exception_message since it inherits the constructor.

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.

2 participants