Use this skill when:
Unterminated string or JSON truncation errorsDo NOT use this skill when:
The Write tool serializes file content as a JSON string for transport. CJK characters occupy 3-4 bytes each in UTF-8. When a multi-byte character happens to cross an internal buffer boundary, the JSON string gets truncated, causing Unterminated string errors. ASCII-only content avoids this because each character is exactly 1 byte.
Key facts:
Scope clarification: The Read and Edit tools are not affected by this issue — Read only reads (never writes), and Edit's
oldString/newStringare short strings (< 30 lines each) that never trigger truncation. Only the Write tool has this limitation.
Evaluate the file first: if any condition below is met, go directly to skeleton + Edit — do NOT try Write first:
- File > 50 lines → skeleton + Edit
- Content contains CJK / special characters → ASCII skeleton + Edit to fill CJK
- Write already failed → switch immediately, never retry
Only for files that are short (< 50 lines) and pure ASCII may you try Write directly — but if it fails, switch immediately.
Never retry a failed Write with the same content — this is the hard constraint of this Skill.
ScenarioStrategy< 50 lines + pure ASCIIYou may try Write directly; for files > 50 lines or with CJK, go directly to skeleton + Edit> 50 lines / contains CJK / Write failedSkeleton + EditSmall edit to existing file (< 30 lines change)Edit tool directlyLarge rewrite of existing file / CJK contentRead file → Edit in small chunks with unique anchors
When unsure, try the simpler approach first and fall back to skeleton+Edit if it fails. Never retry a failed Write.
Trigger condition: Creating a new file expected to be > 50 lines, or containing CJK content.
Steps:
PLACEHOLDER_xxxExample — writing a 200-line Python file:
Step 1 — Write the skeleton:
python
import argparse
import base64
import json
from paddleocr import PaddleOCR
from openai import OpenAI
API_BASE = "PLACEHOLDER_API_BASE"
API_KEY = "PLACEHOLDER_API_KEY"
PROMPT = "PLACEHOLDER_PROMPT"
def get_ocr():
pass # PLACEHOLDER_get_ocr
def detect_texts(image_path):
pass # PLACEHOLDER_detect_texts
def extract_json(text):
pass # PLACEHOLDER_extract_json
def main():
pass # PLACEHOLDER_main
if __name__ == "__main__":
main()
Step 2 — Fill each function with Edit (one at a time):
text
Edit(filePath="/path/to/file.py",
oldString="pass # PLACEHOLDER_get_ocr",
newString="ocr = PaddleOCR(use_angle_cls=True, lang='ch')\n return ocr")
Edit(filePath="/path/to/file.py",
oldString="pass # PLACEHOLDER_detect_texts",
newString="result = ocr.ocr(image_path, cls=True)\n return result")
Trigger condition: Modifying an existing file that is already large or contains CJK.
Trigger condition: Need to add content at the end of an existing file.
The Edit tool can only replace, not append. To add content at the end of a file:
oldString, then repeat it in newString after the new content.if __name__ == "__main__":, use that line as the anchor and replace it with new_function_code\n\nif __name__ == "__main__":.# END_OF_FILE) via Edit, use it as anchor for subsequent appends, then remove it with a final Edit. ⚠️ Prefer stable anchors (like if __name__ == "__main__":) whenever available — if the agent is interrupted before the final cleanup Edit, the marker will remain in the file as residue.Trigger condition: File content includes Chinese, Japanese, Korean, or other non-ASCII characters.
"\u8bc6\u522b" instead of "识别") — this keeps the file ASCII-safe but less readable.Example — Python file with Chinese prompts:
Step 1 — Skeleton with placeholders:
python
PROMPT_SYSTEM = "PLACEHOLDER_prompt_system"
PROMPT_USER = "PLACEHOLDER_prompt_user"
ERROR_MSG = "PLACEHOLDER_error_msg"
Step 2 — Fill with Edit:
text
Edit(filePath="/path/to/file.py",
oldString='PROMPT_SYSTEM = "PLACEHOLDER_prompt_system"',
newString='PROMPT_SYSTEM = "你是一个专业的AI助手,请用中文回答问题"')
Trigger condition: Writing config/data files that lack code-style comment placeholders.
These files lack code-style comment placeholders. Strategy:
0, false, null) rather than a string — a string placeholder like "PLACEHOLDER" would break JSON type validity. Edit the field afterward with a short Edit call to replace the placeholder with the real value, or use a two-step Edit: first replace with a string, then fix the type.# PLACEHOLDER_key_name comments as anchors on the line above the value to replace.A good skeleton should include:
pass as multiple pass statements cause Edit tool Found multiple matches errors.main() or entry point at the bottomFor classes, use # PLACEHOLDER_ClassName_method_name format to ensure uniqueness across methods:
python
class MyHandler:
def __init__(self):
pass # PLACEHOLDER_MyHandler_init
def process(self, data):
pass # PLACEHOLDER_MyHandler_process
For JS/TS, use // PLACEHOLDER_funcName comments instead.
If an Edit call fails with oldString not found:
If an Edit call fails with Found multiple matches:
replaceAll: true if you genuinely want to replace every occurrence (e.g., renaming a variable)ErrorCauseFixUnterminated stringWrite content contains CJK or is too long; JSON truncatedSwitch to skeleton + Edit immediately; do not retry WriteoldString not foundFile content doesn't match oldString (stale after prior edit, whitespace differences)Re-Read the file; construct oldString from actual contentFound multiple matchesoldString appears multiple times (e.g., bare pass)Add more surrounding context to make oldString unique; or use replaceAll: true``File not foundParent directory doesn't exist for new fileCreate directory first with mkdir -p, then WriteWrite succeeds but Read shows incomplete contentJSON truncation at end of file — Write didn't error but content was cut offUse Edit to fill in missing parts, or rewrite with skeleton + EditPowerShell corrupts multi-line codePowerShell interprets quotes/backticks/curly braces in stringsWrite code to a .py/.js file first, then execute the file
pass # PLACEHOLDER_func_name) — bare pass triggers Found multiple matches on every subsequent Edit.oldString not found.python -c "..." with multi-line code in PowerShell → same string handling issues; code gets mangled before executionAfter completing all file writes/edits:
file.py (120 lines, verified)" — no more detail needed