fix: Handle EntityCreationError as conflict (#541) · basicmachines-co/basic-memory@343a6e1 · GitHub
Skip to content

Commit 343a6e1

Browse files
authored
fix: Handle EntityCreationError as conflict (#541)
Signed-off-by: phernandez <paul@basicmachines.co>
1 parent a0e754b commit 343a6e1

5 files changed

Lines changed: 77 additions & 13 deletions

File tree

src/basic_memory/api/app.py

Lines changed: 27 additions & 1 deletion

src/basic_memory/services/entity_service.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@
3434
DirectoryDeleteError,
3535
)
3636
from basic_memory.services import BaseService, FileService
37-
from basic_memory.services.exceptions import EntityCreationError, EntityNotFoundError
37+
from basic_memory.services.exceptions import (
38+
EntityAlreadyExistsError,
39+
EntityCreationError,
40+
EntityNotFoundError,
41+
)
3842
from basic_memory.services.link_resolver import LinkResolver
3943
from basic_memory.services.search_service import SearchService
4044
from basic_memory.utils import generate_permalink
@@ -216,7 +220,7 @@ async def create_entity(self, schema: EntitySchema) -> EntityModel:
216220
file_path = Path(schema.file_path)
217221

218222
if await self.file_service.exists(file_path):
219-
raise EntityCreationError(
223+
raise EntityAlreadyExistsError(
220224
f"file for entity {schema.directory}/{schema.title} already exists: {file_path}"
221225
)
222226

@@ -356,7 +360,7 @@ async def fast_write_entity(
356360
file_path = Path(existing.file_path) if existing else Path(schema.file_path)
357361

358362
if not existing and await self.file_service.exists(file_path):
359-
raise EntityCreationError(
363+
raise EntityAlreadyExistsError(
360364
f"file for entity {schema.directory}/{schema.title} already exists: {file_path}"
361365
)
362366

src/basic_memory/services/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class EntityCreationError(Exception):
1616
pass
1717

1818

19+
class EntityAlreadyExistsError(EntityCreationError):
20+
"""Raised when an entity file already exists"""
21+
22+
pass
23+
24+
1925
class DirectoryOperationError(Exception):
2026
"""Raised when directory operations fail"""
2127

tests/api/v2/test_knowledge_router.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,34 @@ async def test_create_entity(client: AsyncClient, file_service, v2_project_url):
181181
assert data["content"] in file_content
182182

183183

184+
@pytest.mark.asyncio
185+
async def test_create_entity_conflict_returns_409(client: AsyncClient, v2_project_url):
186+
"""Test creating a duplicate entity returns 409 Conflict."""
187+
data = {
188+
"title": "TestV2EntityConflict",
189+
"directory": "conflict",
190+
"entity_type": "note",
191+
"content_type": "text/markdown",
192+
"content": "Original content for conflict",
193+
}
194+
195+
response = await client.post(
196+
f"{v2_project_url}/knowledge/entities",
197+
json=data,
198+
params={"fast": False},
199+
)
200+
assert response.status_code == 200
201+
202+
response = await client.post(
203+
f"{v2_project_url}/knowledge/entities",
204+
json=data,
205+
params={"fast": False},
206+
)
207+
assert response.status_code == 409
208+
expected_detail = "Note already exists. Use edit_note to modify it, or delete it first."
209+
assert response.json()["detail"] == expected_detail
210+
211+
184212
@pytest.mark.asyncio
185213
async def test_create_entity_returns_content(client: AsyncClient, file_service, v2_project_url):
186214
"""Test creating an entity always returns file content with frontmatter."""

tests/services/test_search_service.py

Lines changed: 9 additions & 9 deletions

0 commit comments

Comments
 (0)