| |
| """ |
| Debug script to find where .lower() is being called on non-strings |
| """ |
|
|
| import os |
| import sys |
|
|
| |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) |
|
|
| |
| os.environ["ANTHROPIC_API_KEY"] = "test-key" |
|
|
| def find_lower_calls(): |
| """Find all .lower() calls in the code""" |
| print("Searching for all .lower() calls in app.py...") |
| print("-" * 60) |
| |
| with open('app.py', 'r') as f: |
| lines = f.readlines() |
| |
| lower_calls = [] |
| for i, line in enumerate(lines, 1): |
| if '.lower()' in line: |
| lower_calls.append((i, line.strip())) |
| |
| print(f"Found {len(lower_calls)} .lower() calls:\n") |
| for line_num, line in lower_calls: |
| print(f"Line {line_num}: {line}") |
| |
| if 'isinstance' in lines[line_num-2:line_num]: |
| print(" β
Has type checking") |
| else: |
| print(" β οΈ No type checking nearby") |
| print() |
|
|
| def test_problematic_inputs(): |
| """Test inputs that might cause .lower() errors""" |
| print("\nTesting problematic inputs...") |
| print("-" * 60) |
| |
| |
| test_inputs = [ |
| "normal string", |
| ["list", "of", "strings"], |
| {"dict": "value"}, |
| 123, |
| None, |
| [{"nested": "structure"}], |
| b"bytes string", |
| ] |
| |
| for test_input in test_inputs: |
| print(f"\nInput: {repr(test_input)} (type: {type(test_input)})") |
| |
| |
| try: |
| result = test_input.lower() |
| print(f" β
.lower() works: {result}") |
| except AttributeError as e: |
| print(f" β .lower() fails: {e}") |
| |
| |
| try: |
| if isinstance(test_input, str): |
| result = test_input.lower() |
| print(f" β
With type check: {result}") |
| else: |
| result = str(test_input).lower() |
| print(f" β
With str() conversion: {result}") |
| except Exception as e: |
| print(f" β Even with protection: {e}") |
|
|
| def test_message_content(): |
| """Test what might be in message.content""" |
| print("\n\nTesting message content scenarios...") |
| print("-" * 60) |
| |
| |
| class MockMessage: |
| def __init__(self, content): |
| self.content = content |
| |
| test_messages = [ |
| MockMessage("Normal text content"), |
| MockMessage(["List", "content"]), |
| MockMessage({"type": "text", "content": "dict content"}), |
| MockMessage(None), |
| ] |
| |
| for i, msg in enumerate(test_messages): |
| print(f"\nMessage {i}: content = {repr(msg.content)}") |
| |
| |
| if hasattr(msg, "content") and msg.content: |
| content = msg.content |
| print(f" Content type: {type(content)}") |
| |
| |
| try: |
| content = content.strip() |
| print(f" β
.strip() works") |
| except AttributeError: |
| print(f" β .strip() fails - content is not a string!") |
| |
| |
| if isinstance(content, list): |
| content = " ".join(str(item) for item in content) |
| print(f" β
Converted list to string: {content}") |
| elif not isinstance(content, str): |
| content = str(content) |
| print(f" β
Converted to string: {content}") |
|
|
| if __name__ == "__main__": |
| print("=" * 80) |
| print("DEBUG: Finding .lower() error sources") |
| print("=" * 80) |
| |
| find_lower_calls() |
| test_problematic_inputs() |
| test_message_content() |
| |
| print("\n" + "=" * 80) |
| print("CONCLUSION:") |
| print("The error likely occurs when message.content is a list instead of string") |
| print("This can happen with multimodal messages or tool responses") |
| print("Solution: Always check type before calling .lower() or .strip()") |
| print("=" * 80) |