diff --git a/src/claude_agent_sdk/_internal/message_parser.py b/src/claude_agent_sdk/_internal/message_parser.py index 931cc2a63..160bd745e 100644 --- a/src/claude_agent_sdk/_internal/message_parser.py +++ b/src/claude_agent_sdk/_internal/message_parser.py @@ -147,6 +147,11 @@ def parse_message(data: dict[str, Any]) -> Message | None: raise MessageParseError( f"Missing required field in user message: {e}", data ) from e + except (TypeError, AttributeError) as e: + # e.g. data["message"] is not a dict, so indexing into it fails + raise MessageParseError( + f"Malformed user message: {e}", data + ) from e case "assistant": try: @@ -222,6 +227,11 @@ def parse_message(data: dict[str, Any]) -> Message | None: raise MessageParseError( f"Missing required field in assistant message: {e}", data ) from e + except (TypeError, AttributeError) as e: + # e.g. data["message"] is not a dict, so indexing into it fails + raise MessageParseError( + f"Malformed assistant message: {e}", data + ) from e case "system": try: diff --git a/tests/test_message_parser.py b/tests/test_message_parser.py index e55fd1556..0962d3c6e 100644 --- a/tests/test_message_parser.py +++ b/tests/test_message_parser.py @@ -976,6 +976,13 @@ def test_parse_invalid_data_type(self): assert "Invalid message data type" in str(exc_info.value) assert "expected dict, got str" in str(exc_info.value) + def test_parse_non_dict_message_field(self): + """A non-dict 'message' field raises MessageParseError, not a bare TypeError.""" + for message_type in ("user", "assistant"): + with pytest.raises(MessageParseError) as exc_info: + parse_message({"type": message_type, "message": "not a dict"}) + assert f"Malformed {message_type} message" in str(exc_info.value) + def test_parse_missing_type_field(self): """Test that missing 'type' field raises MessageParseError.""" with pytest.raises(MessageParseError) as exc_info: