Skip to content

Commit 32cba5b

Browse files
committed
refactor: improve error messages for file hash validation
1 parent c77cb4f commit 32cba5b

File tree

4 files changed

+33
-23
lines changed

4 files changed

+33
-23
lines changed

src/mcp_text_editor/handlers/append_text_file_contents.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ async def run_tool(self, arguments: Dict[str, Any]) -> Sequence[TextContent]:
8787
# Create patch for append operation
8888
result = await self.editor.edit_file_contents(
8989
file_path,
90-
expected_hash=arguments["file_hash"],
90+
expected_file_hash=arguments["file_hash"],
9191
patches=[
9292
{
9393
"start": total_lines + 1,

src/mcp_text_editor/handlers/create_text_file.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async def run_tool(self, arguments: Dict[str, Any]) -> Sequence[TextContent]:
6868
# Create new file using edit_file_contents with empty expected_hash
6969
result = await self.editor.edit_file_contents(
7070
file_path,
71-
expected_hash="", # Empty hash for new file
71+
expected_file_hash="", # Empty hash for new file
7272
patches=[
7373
{
7474
"start": 1,

src/mcp_text_editor/handlers/patch_text_file_contents.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ async def run_tool(self, arguments: Dict[str, Any]) -> Sequence[TextContent]:
9494
# Apply patches using editor.edit_file_contents
9595
result = await self.editor.edit_file_contents(
9696
file_path=file_path,
97-
expected_hash=arguments["file_hash"],
97+
expected_file_hash=arguments["file_hash"],
9898
patches=arguments["patches"],
9999
encoding=encoding,
100100
)

src/mcp_text_editor/text_editor.py

+30-20
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ async def read_file_contents(
223223
async def edit_file_contents(
224224
self,
225225
file_path: str,
226-
expected_hash: str,
226+
expected_file_hash: str,
227227
patches: List[Dict[str, Any]],
228228
encoding: str = "utf-8",
229229
) -> Dict[str, Any]:
@@ -252,7 +252,7 @@ async def edit_file_contents(
252252
self._validate_file_path(file_path)
253253
try:
254254
if not os.path.exists(file_path):
255-
if expected_hash not in ["", None]: # Allow null hash
255+
if expected_file_hash not in ["", None]: # Allow null hash
256256
return self.create_error_response(
257257
"File not found and non-empty hash provided",
258258
suggestion="append",
@@ -270,31 +270,31 @@ async def edit_file_contents(
270270
hint="Please check file permissions and try again",
271271
)
272272
# Initialize empty state for new file
273-
current_content = ""
274-
current_hash = ""
273+
current_file_content = ""
274+
current_file_hash = ""
275275
lines: List[str] = []
276276
encoding = "utf-8"
277277
else:
278278
# Read current file content and verify hash
279279
(
280-
current_content,
280+
current_file_content,
281281
_,
282282
_,
283-
current_hash,
283+
current_file_hash,
284284
total_lines,
285285
_,
286286
) = await self.read_file_contents(file_path, encoding=encoding)
287287

288288
# Treat empty file as new file
289-
if not current_content:
290-
current_content = ""
291-
current_hash = ""
289+
if not current_file_content:
290+
current_file_content = ""
291+
current_file_hash = ""
292292
lines = []
293-
elif current_content and expected_hash == "":
293+
elif current_file_content and expected_file_hash == "":
294294
return self.create_error_response(
295295
"Unexpected error - Cannot treat existing file as new",
296296
)
297-
elif current_hash != expected_hash:
297+
elif current_file_hash != expected_file_hash:
298298
suggestion = "patch"
299299
hint = "Please use get_text_file_contents tool to get the current content and hash"
300300

@@ -304,8 +304,8 @@ async def edit_file_contents(
304304
hint=hint,
305305
)
306306
else:
307-
lines = current_content.splitlines(keepends=True)
308-
lines = current_content.splitlines(keepends=True)
307+
lines = current_file_content.splitlines(keepends=True)
308+
lines = current_file_content.splitlines(keepends=True)
309309

310310
# Convert patches to EditPatch objects
311311
patch_objects = [EditPatch.model_validate(p) for p in patches]
@@ -356,16 +356,26 @@ async def edit_file_contents(
356356
"result": "error",
357357
"reason": "End line must be greater than or equal to start line",
358358
"file_hash": None,
359-
"content": current_content,
359+
"content": current_file_content,
360360
}
361361

362362
# Handle unexpected empty hash for existing file
363363
if (
364364
os.path.exists(file_path)
365-
and current_content
366-
and expected_hash == ""
365+
and current_file_content
366+
and expected_file_hash == ""
367367
):
368-
return {"result": "error", "reason": "Unexpected error"}
368+
return {
369+
"result": "error",
370+
"reason": "File hash validation required: Empty hash provided for existing file",
371+
"details": {
372+
"file_path": file_path,
373+
"current_file_hash": self.calculate_hash(
374+
current_file_content
375+
),
376+
"expected_file_hash": expected_file_hash,
377+
},
378+
}
369379

370380
# Calculate line ranges for zero-based indexing
371381
start_zero = start - 1
@@ -379,7 +389,7 @@ async def edit_file_contents(
379389
expected_range_hash = patch.range_hash
380390

381391
# Determine operation type and validate hash requirements
382-
if not os.path.exists(file_path) or not current_content:
392+
if not os.path.exists(file_path) or not current_file_content:
383393
# New file or empty file - treat as insertion
384394
is_insertion = True
385395
elif start_zero >= len(lines):
@@ -418,15 +428,15 @@ async def edit_file_contents(
418428
if not contents.strip():
419429
return {
420430
"result": "ok",
421-
"file_hash": current_hash, # Return current hash since no changes made
431+
"file_hash": current_file_hash, # Return current hash since no changes made
422432
"hint": "For content deletion, please consider using delete_text_file_contents instead of patch with empty content",
423433
"suggestion": "delete",
424434
}
425435

426436
# Set suggestions for alternative tools
427437
suggestion_text: Optional[str] = None
428438
hint_text: Optional[str] = None
429-
if not os.path.exists(file_path) or not current_content:
439+
if not os.path.exists(file_path) or not current_file_content:
430440
suggestion_text = "append"
431441
hint_text = "For new or empty files, please consider using append_text_file_contents instead"
432442
elif is_insertion:

0 commit comments

Comments
 (0)