diff --git a/opentelemetry-api/src/opentelemetry/attributes/__init__.py b/opentelemetry-api/src/opentelemetry/attributes/__init__.py index 5116c2fdd8..8fc80125a8 100644 --- a/opentelemetry-api/src/opentelemetry/attributes/__init__.py +++ b/opentelemetry-api/src/opentelemetry/attributes/__init__.py @@ -190,7 +190,7 @@ def _clean_extended_attribute_value( # pylint: disable=too-many-branches except Exception: raise TypeError( f"Invalid type {type(value).__name__} for attribute value. " - f"Expected one of {[valid_type.__name__ for valid_type in _VALID_ANY_VALUE_TYPES]} or a " + f"Expected one of {[getattr(valid_type, '__name__', getattr(valid_type, '_name', None)) for valid_type in _VALID_ANY_VALUE_TYPES]} or a " "sequence of those types", ) diff --git a/opentelemetry-api/tests/attributes/test_attributes.py b/opentelemetry-api/tests/attributes/test_attributes.py index 8cb6f35fbc..6781b05352 100644 --- a/opentelemetry-api/tests/attributes/test_attributes.py +++ b/opentelemetry-api/tests/attributes/test_attributes.py @@ -320,3 +320,25 @@ def __str__(self): self.assertEqual( "", cleaned_value ) + + def test_invalid_type_error_message(self): + """Test that invalid types that cannot be converted to string raise TypeError with proper message. + + This test specifically addresses issue #4821 where on Python 3.9, the error message + generation would fail with AttributeError when accessing __name__ on generic types like Mapping. + """ + + class UnstringifiableObject: + """An object that cannot be converted to string.""" + + def __str__(self): + raise ValueError("Cannot convert to string") + + invalid_value = UnstringifiableObject() + + # Should return None and log warning, not raise AttributeError + cleaned_value = _clean_extended_attribute( + "test_key", invalid_value, None + ) + + self.assertIsNone(cleaned_value)