diff --git a/src/bedrock_agentcore/memory/integrations/strands/session_manager.py b/src/bedrock_agentcore/memory/integrations/strands/session_manager.py index d6d20ab7..5e6ac7bc 100644 --- a/src/bedrock_agentcore/memory/integrations/strands/session_manager.py +++ b/src/bedrock_agentcore/memory/integrations/strands/session_manager.py @@ -322,8 +322,10 @@ def read_session(self, session_id: str, **kwargs: Any) -> Optional[Session]: max_results=1, ) if events: - session_data = json.loads(events[0].get("payload", {})[0].get("blob")) - return Session.from_dict(session_data) + payload = events[0].get("payload") or [] + if payload: + session_data = json.loads(payload[0].get("blob")) + return Session.from_dict(session_data) # 2. Fallback: check for legacy event and migrate legacy_actor_id = f"{LEGACY_SESSION_PREFIX}{session_id}" @@ -335,7 +337,10 @@ def read_session(self, session_id: str, **kwargs: Any) -> Optional[Session]: ) if events: old_event = events[0] - session_data = json.loads(old_event.get("payload", {})[0].get("blob")) + payload = old_event.get("payload") or [] + if not payload: + return None + session_data = json.loads(payload[0].get("blob")) session = Session.from_dict(session_data) # Migrate: create new event with metadata, delete old if self.persistence_mode is not PersistenceMode.NONE: diff --git a/tests/bedrock_agentcore/memory/integrations/strands/test_agentcore_memory_session_manager.py b/tests/bedrock_agentcore/memory/integrations/strands/test_agentcore_memory_session_manager.py index 35d3e8b9..9a68530e 100644 --- a/tests/bedrock_agentcore/memory/integrations/strands/test_agentcore_memory_session_manager.py +++ b/tests/bedrock_agentcore/memory/integrations/strands/test_agentcore_memory_session_manager.py @@ -207,10 +207,10 @@ def test_read_session_legacy_migration(self, session_manager, mock_memory_client """Test reading a legacy session event triggers migration.""" legacy_session_data = '{"session_id": "test-session-456", "session_type": "AGENT"}' - # First call (new approach with metadata) returns empty + # First call returns an event whose payload is no longer available # Second call (legacy actor_id) returns the legacy event mock_memory_client.list_events.side_effect = [ - [], # New approach returns nothing + [{"eventId": "expired-session-event", "payload": []}], [{"eventId": "legacy-event-1", "payload": [{"blob": legacy_session_data}]}], # Legacy approach ] mock_memory_client.gmdp_client.create_event.return_value = {"event": {"eventId": "new-event-1"}} @@ -234,6 +234,19 @@ def test_read_session_legacy_migration(self, session_manager, mock_memory_client assert delete_call_kwargs["actorId"] == "session_test-session-456" assert delete_call_kwargs["eventId"] == "legacy-event-1" + def test_read_session_empty_payload_returns_none(self, session_manager, mock_memory_client): + """Test session events with empty payloads are treated as unavailable.""" + mock_memory_client.list_events.side_effect = [ + [{"eventId": "session-event-1", "payload": []}], + [{"eventId": "legacy-event-1", "payload": []}], + ] + + result = session_manager.read_session("test-session-456") + + assert result is None + mock_memory_client.gmdp_client.create_event.assert_not_called() + mock_memory_client.gmdp_client.delete_event.assert_not_called() + def test_create_agent(self, session_manager): """Test creating an agent.""" session_agent = SessionAgent(agent_id="test-agent-123", state={}, conversation_manager_state={})