Skip to content

Commit f64d5b2

Browse files
committed
improve error messages for tools
Signed-off-by: phernandez <paul@basicmachines.co>
1 parent 69a625a commit f64d5b2

15 files changed

Lines changed: 838 additions & 194 deletions

src/basic_memory/mcp/tools/delete_note.py

Lines changed: 159 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,157 @@
1+
from textwrap import dedent
12
from typing import Optional
23

4+
from loguru import logger
5+
36
from basic_memory.mcp.tools.utils import call_delete
47
from basic_memory.mcp.server import mcp
58
from basic_memory.mcp.async_client import client
69
from basic_memory.mcp.project_session import get_active_project
710
from basic_memory.schemas import DeleteEntitiesResponse
811

912

13+
def _format_delete_error_response(error_message: str, identifier: str) -> str:
14+
"""Format helpful error responses for delete failures that guide users to successful deletions."""
15+
16+
# Note not found errors
17+
if "entity not found" in error_message.lower() or "not found" in error_message.lower():
18+
search_term = identifier.split("/")[-1] if "/" in identifier else identifier
19+
title_format = (
20+
identifier.split("/")[-1].replace("-", " ").title() if "/" in identifier else identifier
21+
)
22+
permalink_format = identifier.lower().replace(" ", "-")
23+
24+
return dedent(f"""
25+
# Delete Failed - Note Not Found
26+
27+
The note '{identifier}' could not be found for deletion.
28+
29+
## This might mean:
30+
1. **Already deleted**: The note may have been deleted previously
31+
2. **Wrong identifier**: The identifier format might be incorrect
32+
3. **Different project**: The note might be in a different project
33+
34+
## How to verify:
35+
1. **Search for the note**: Use `search_notes("{search_term}")` to find it
36+
2. **Try different formats**:
37+
- If you used a permalink like "folder/note-title", try just the title: "{title_format}"
38+
- If you used a title, try the permalink format: "{permalink_format}"
39+
40+
3. **Check if already deleted**: Use `list_directory("/")` to see what notes exist
41+
4. **Check current project**: Use `get_current_project()` to verify you're in the right project
42+
43+
## If the note actually exists:
44+
```
45+
# First, find the correct identifier:
46+
search_notes("{identifier}")
47+
48+
# Then delete using the correct identifier:
49+
delete_note("correct-identifier-from-search")
50+
```
51+
52+
## If you want to delete multiple similar notes:
53+
Use search to find all related notes and delete them one by one.
54+
""").strip()
55+
56+
# Permission/access errors
57+
if (
58+
"permission" in error_message.lower()
59+
or "access" in error_message.lower()
60+
or "forbidden" in error_message.lower()
61+
):
62+
return f"""# Delete Failed - Permission Error
63+
64+
You don't have permission to delete '{identifier}': {error_message}
65+
66+
## How to resolve:
67+
1. **Check permissions**: Verify you have delete/write access to this project
68+
2. **File locks**: The note might be open in another application
69+
3. **Project access**: Ensure you're in the correct project with proper permissions
70+
71+
## Alternative actions:
72+
- Check current project: `get_current_project()`
73+
- Switch to correct project: `switch_project("project-name")`
74+
- Verify note exists first: `read_note("{identifier}")`
75+
76+
## If you have read-only access:
77+
Send a message to support@basicmachines.co to request deletion, or ask someone with write access to delete the note."""
78+
79+
# Server/filesystem errors
80+
if (
81+
"server error" in error_message.lower()
82+
or "filesystem" in error_message.lower()
83+
or "disk" in error_message.lower()
84+
):
85+
return f"""# Delete Failed - System Error
86+
87+
A system error occurred while deleting '{identifier}': {error_message}
88+
89+
## Immediate steps:
90+
1. **Try again**: The error might be temporary
91+
2. **Check file status**: Verify the file isn't locked or in use
92+
3. **Check disk space**: Ensure the system has adequate storage
93+
94+
## Troubleshooting:
95+
- Verify note exists: `read_note("{identifier}")`
96+
- Check project status: `get_current_project()`
97+
- Try again in a few moments
98+
99+
## If problem persists:
100+
Send a message to support@basicmachines.co - there may be a filesystem or database issue."""
101+
102+
# Database/sync errors
103+
if "database" in error_message.lower() or "sync" in error_message.lower():
104+
return f"""# Delete Failed - Database Error
105+
106+
A database error occurred while deleting '{identifier}': {error_message}
107+
108+
## This usually means:
109+
1. **Sync conflict**: The file system and database are out of sync
110+
2. **Database lock**: Another operation is accessing the database
111+
3. **Corrupted entry**: The database entry might be corrupted
112+
113+
## Steps to resolve:
114+
1. **Try again**: Wait a moment and retry the deletion
115+
2. **Check note status**: `read_note("{identifier}")` to see current state
116+
3. **Manual verification**: Use `list_directory()` to see if file still exists
117+
118+
## If the note appears gone but database shows it exists:
119+
Send a message to support@basicmachines.co - a manual database cleanup may be needed."""
120+
121+
# Generic fallback
122+
return f"""# Delete Failed
123+
124+
Error deleting note '{identifier}': {error_message}
125+
126+
## General troubleshooting:
127+
1. **Verify the note exists**: `read_note("{identifier}")` or `search_notes("{identifier}")`
128+
2. **Check permissions**: Ensure you can edit/delete files in this project
129+
3. **Try again**: The error might be temporary
130+
4. **Check project**: Make sure you're in the correct project
131+
132+
## Step-by-step approach:
133+
```
134+
# 1. Confirm note exists and get correct identifier
135+
search_notes("{identifier}")
136+
137+
# 2. Read the note to verify access
138+
read_note("correct-identifier-from-search")
139+
140+
# 3. Try deletion with correct identifier
141+
delete_note("correct-identifier-from-search")
142+
```
143+
144+
## Alternative approaches:
145+
- Check what notes exist: `list_directory("/")`
146+
- Verify current project: `get_current_project()`
147+
- Switch projects if needed: `switch_project("correct-project")`
148+
149+
## Need help?
150+
If the note should be deleted but the operation keeps failing, send a message to support@basicmachines.co."""
151+
152+
10153
@mcp.tool(description="Delete a note by title or permalink")
11-
async def delete_note(identifier: str, project: Optional[str] = None) -> bool:
154+
async def delete_note(identifier: str, project: Optional[str] = None) -> bool | str:
12155
"""Delete a note from the knowledge base.
13156
14157
Args:
@@ -31,6 +174,18 @@ async def delete_note(identifier: str, project: Optional[str] = None) -> bool:
31174
active_project = get_active_project(project)
32175
project_url = active_project.project_url
33176

34-
response = await call_delete(client, f"{project_url}/knowledge/entities/{identifier}")
35-
result = DeleteEntitiesResponse.model_validate(response.json())
36-
return result.deleted
177+
try:
178+
response = await call_delete(client, f"{project_url}/knowledge/entities/{identifier}")
179+
result = DeleteEntitiesResponse.model_validate(response.json())
180+
181+
if result.deleted:
182+
logger.info(f"Successfully deleted note: {identifier}")
183+
return True
184+
else:
185+
logger.warning(f"Delete operation completed but note was not deleted: {identifier}")
186+
return False
187+
188+
except Exception as e:
189+
logger.error(f"Delete failed for '{identifier}': {e}")
190+
# Return formatted error message for better user experience
191+
return _format_delete_error_response(str(e), identifier)

0 commit comments

Comments
 (0)