Overview
Apply text changes to one or more files in your workspace. This is used to execute the edits returned by other tools like rename, format, or code actions.
Request
Workspace edit containing all changes Map of file URIs to arrays of text edits
Optional description of the edit (e.g., “Rename variable”)
Response
Whether the edit was successfully applied
Error message if applied is false
Number of files that were changed
Total number of text edits applied
Example Request
cURL
Python
JavaScript
TypeScript
curl -X POST https://api.pylancemcp.dev/v1/tools/call \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "apply_workspace_edit",
"arguments": {
"edit": {
"changes": {
"file:///workspace/app/utils.py": [
{
"range": {
"start": {"line": 8, "character": 4},
"end": {"line": 8, "character": 19}
},
"newText": "compute_total"
}
]
}
},
"label": "Rename function"
}
}'
Example Response
{
"applied" : true ,
"filesModified" : 3 ,
"totalEdits" : 12
}
Use Cases
Apply Rename Edits
# 1. Get rename edits
rename = client.rename_symbol(
uri = "file:///workspace/app/utils.py" ,
line = 8 ,
character = 4 ,
new_name = "compute_total"
)
# 2. Apply the edits
result = client.apply_workspace_edit(
edit = rename.changes,
label = "Rename calculate_total to compute_total"
)
if result.applied:
print ( f "✅ Renamed across { result.files_modified } files" )
# 1. Get format edits
formatted = client.format_document(
uri = "file:///workspace/app/views.py"
)
# 2. Convert to workspace edit format
workspace_edit = {
"file:///workspace/app/views.py" : formatted.edits
}
# 3. Apply the formatting
result = client.apply_workspace_edit(
edit = workspace_edit,
label = "Format document"
)
Apply Code Action
# 1. Get code actions
actions = client.get_code_actions( uri = file_uri, range = error_range)
# 2. Find the quickfix to apply
quickfix = next (a for a in actions.actions if a.kind == "quickfix" )
# 3. Apply it
result = client.apply_workspace_edit(
edit = quickfix.edit,
label = quickfix.title
)
if result.applied:
print ( f "✅ Applied fix: { quickfix.title } " )
Batch Multiple Edits
# Apply edits to multiple files at once
workspace_edit = {
"file:///workspace/app/utils.py" : [
{ "range" : { ... }, "newText" : "new_name" }
],
"file:///workspace/app/views.py" : [
{ "range" : { ... }, "newText" : "new_name" },
{ "range" : { ... }, "newText" : "import new_name" }
],
"file:///workspace/tests/test_utils.py" : [
{ "range" : { ... }, "newText" : "new_name" }
]
}
result = client.apply_workspace_edit(
edit = workspace_edit,
label = "Update references"
)
Edit Application Order
Edits are applied in a specific order to prevent conflicts:
Sort by File
Group edits by file URI
Sort by Position
Within each file, sort edits from bottom to top (descending line/character)
Apply Edits
Apply each edit, preventing line number shifts
Verify
Confirm all edits applied successfully
Bottom-to-top ordering ensures that edits don’t affect the positions of subsequent edits.
Error Handling
The operation is atomic - either all edits succeed or none are applied:
result = client.apply_workspace_edit( edit = workspace_edit)
if not result.applied:
if "FILE_NOT_FOUND" in result.failure_reason:
print ( "❌ One or more files don't exist" )
elif "PERMISSION_DENIED" in result.failure_reason:
print ( "❌ Cannot write to files" )
elif "CONFLICTING_EDITS" in result.failure_reason:
print ( "❌ Edits overlap - cannot apply safely" )
else :
print ( f "❌ Failed: { result.failure_reason } " )
Safety Features
Atomic Operation All files updated together or none at all
Conflict Detection Overlapping edits are rejected
Validation File paths and ranges validated before applying
Rollback Support Failed edits don’t leave partial changes
Best Practices
Preview First : Show user what will change before applying
Use Version Control : Commit before large edits so you can revert
Validate Ranges : Ensure all ranges are valid before applying
Add Labels : Always provide descriptive labels for better UX
Batch Edits : Apply multiple files in one operation instead of separate calls
Non-Overlapping : Ensure edits don’t overlap for faster application
Minimize Scope : Only edit necessary files and ranges
Error Responses
Code Reason Solution FILE_NOT_FOUNDOne or more files don’t exist Verify all file URIs PERMISSION_DENIEDCannot write to file Check file permissions INVALID_RANGERange out of bounds Validate line/character positions CONFLICTING_EDITSOverlapping edits in same file Resolve conflicts first FILE_MODIFIEDFile changed since edits were generated Regenerate edits READONLY_FILEFile is read-only Remove read-only flag
Rollback
If you need to undo an edit:
# Save original content before applying
original_content = {}
for file_uri in workspace_edit.keys():
with open (file_uri.replace( 'file://' , '' ), 'r' ) as f:
original_content[file_uri] = f.read()
# Apply edit
result = client.apply_workspace_edit( edit = workspace_edit)
# If something went wrong, restore original
if not result.applied or user_wants_undo:
for file_uri, content in original_content.items():
with open (file_uri.replace( 'file://' , '' ), 'w' ) as f:
f.write(content)
Rate Limits
Tier Requests/Hour Requests/Day Max Files/Edit Max Edits/File Free 10 50 5 100 Hobby 250 2,500 20 500 Pro 2,500 25,000 100 5,000 Enterprise Unlimited Unlimited Unlimited Unlimited
Large workspace edits count as one request but may take longer to apply.