@@ -1728,3 +1728,69 @@ async def test_move_entity_with_complex_observations(
17281728 assert "Branch Strategy" in relation_targets
17291729 assert "Multiple" in relation_targets
17301730 assert "Links" in relation_targets
1731+
1732+
1733+ @pytest .mark .asyncio
1734+ async def test_move_entity_with_null_permalink_generates_permalink (
1735+ entity_service : EntityService ,
1736+ project_config : ProjectConfig ,
1737+ entity_repository : EntityRepository ,
1738+ ):
1739+ """Test that moving entity with null permalink generates a new permalink automatically.
1740+
1741+ This tests the fix for issue #155 where entities with null permalinks from the database
1742+ migration would fail validation when being moved. The fix ensures that entities with
1743+ null permalinks get a generated permalink during move operations, regardless of the
1744+ update_permalinks_on_move setting.
1745+ """
1746+ # Create entity through direct database insertion to simulate migrated entity with null permalink
1747+ from basic_memory .models .knowledge import Entity as EntityModel
1748+ from datetime import datetime , timezone
1749+
1750+ # Create an entity with null permalink directly in database (simulating migrated data)
1751+ entity_data = {
1752+ "title" : "Test Entity" ,
1753+ "file_path" : "test/null-permalink-entity.md" ,
1754+ "entity_type" : "note" ,
1755+ "content_type" : "text/markdown" ,
1756+ "permalink" : None , # This is the key - null permalink from migration
1757+ "created_at" : datetime .now (timezone .utc ),
1758+ "updated_at" : datetime .now (timezone .utc ),
1759+ }
1760+
1761+ # Create the entity directly in database
1762+ created_entity = await entity_repository .create (entity_data )
1763+ assert created_entity .permalink is None
1764+
1765+ # Create the physical file
1766+ file_path = project_config .home / created_entity .file_path
1767+ file_path .parent .mkdir (parents = True , exist_ok = True )
1768+ file_path .write_text ("# Test Entity\n \n Content here." )
1769+
1770+ # Configure move without permalink updates (the default setting that previously triggered the bug)
1771+ app_config = BasicMemoryConfig (update_permalinks_on_move = False )
1772+
1773+ # Move entity - this should now succeed and generate a permalink
1774+ moved_entity = await entity_service .move_entity (
1775+ identifier = created_entity .title , # Use title since permalink is None
1776+ destination_path = "moved/test-entity.md" ,
1777+ project_config = project_config ,
1778+ app_config = app_config ,
1779+ )
1780+
1781+ # Verify the move succeeded and a permalink was generated
1782+ assert moved_entity is not None
1783+ assert moved_entity .file_path == "moved/test-entity.md"
1784+ assert moved_entity .permalink is not None
1785+ assert moved_entity .permalink != ""
1786+
1787+ # Verify the moved entity can be used to create an EntityResponse without validation errors
1788+ from basic_memory .schemas .response import EntityResponse
1789+ response = EntityResponse .model_validate (moved_entity )
1790+ assert response .permalink == moved_entity .permalink
1791+
1792+ # Verify the physical file was moved
1793+ old_path = project_config .home / "test/null-permalink-entity.md"
1794+ new_path = project_config .home / "moved/test-entity.md"
1795+ assert not old_path .exists ()
1796+ assert new_path .exists ()
0 commit comments