{"record":{"id":"7762141defacbacd","repo":"HKUDS/DeepTutor","slug":"edit-text-length-must-be-1-max-text-len-got","errorCode":null,"errorMessage":"edit: text length must be 1..{_MAX_TEXT_LEN} (got {len(op.new_text)})","messagePattern":"edit: text length must be 1\\.\\.(.+?) \\(got (.+?)\\)","errorType":"validation","errorClass":"OpValidationError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/memory/ops.py","lineNumber":91,"sourceCode":"        if isinstance(op, AddOp):\n            if not op.text or len(op.text) > _MAX_TEXT_LEN:\n                raise OpValidationError(\n                    f\"add: text length must be 1..{_MAX_TEXT_LEN} (got {len(op.text)})\"\n                )\n            if not op.section or len(op.section) > _MAX_SECTION_LEN:\n                raise OpValidationError(f\"add: invalid section {op.section!r}\")\n            if not op.refs:\n                raise OpValidationError(\"add: refs must be non-empty\")\n            for ref in op.refs:\n                if not is_valid_ref(ref):\n                    raise OpValidationError(f\"add: malformed ref {ref!r}\")\n        elif isinstance(op, EditOp):\n            if not is_entry_id(op.target_id):\n                raise OpValidationError(f\"edit: malformed target_id {op.target_id!r}\")\n            if doc.find(op.target_id) is None:\n                raise OpValidationError(f\"edit: target_id {op.target_id} not found\")\n            if not op.new_text or len(op.new_text) > _MAX_TEXT_LEN:\n                raise OpValidationError(\n                    f\"edit: text length must be 1..{_MAX_TEXT_LEN} (got {len(op.new_text)})\"\n                )\n            if not op.new_refs:\n                raise OpValidationError(\"edit: refs must be non-empty\")\n            for ref in op.new_refs:\n                if not is_valid_ref(ref):\n                    raise OpValidationError(f\"edit: malformed ref {ref!r}\")\n            if op.target_id in deletes:\n                raise OpValidationError(\n                    f\"batch conflict: edit and delete on same id {op.target_id}\"\n                )\n            edits.add(op.target_id)\n        elif isinstance(op, DeleteOp):\n            if not is_entry_id(op.target_id):\n                raise OpValidationError(f\"delete: malformed target_id {op.target_id!r}\")\n            if doc.find(op.target_id) is None:\n                raise OpValidationError(f\"delete: target_id {op.target_id} not found\")\n            if op.reason not in _DELETE_REASONS:","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/memory/ops.py#L73-L109","documentation":"OpValidationError raised in _validate when an EditOp's new_text is empty or longer than _MAX_TEXT_LEN. Replacement text for an existing entry is bounded by the same limit as AddOp text so entries stay within the memory document's size budget; invalid replacement text is rejected before the edit is applied (apply is all-or-nothing).","triggerScenarios":"EditOp(..., new_text='' or new_text longer than _MAX_TEXT_LEN) passed to ops.apply — typically an LLM rewriting an entry into an oversized blob, or code passing None/empty string as 'no change' semantics that the API does not support.","commonSituations":"LLM-generated replacements without clamping; 'clear this entry' implemented as empty text instead of a delete op; diffs or concatenations accidentally producing huge strings; tests probing boundaries.","solutions":["Clamp/reject: require 1.._MAX_TEXT_LEN (import the constant from ops.py) before building the EditOp","To remove content use the dedicated DeleteOp rather than an empty-text edit","Summarize or split oversized replacement text; surface a clear error to the LLM/caller so it retries shorter"],"exampleFix":"# before\nop = EditOp(target_id=eid, new_text=rewritten, new_refs=[ref])\n\n# after\nfrom deeptutor.services.memory.ops import _MAX_TEXT_LEN\nrewritten = rewritten.strip()\nif not rewritten or len(rewritten) > _MAX_TEXT_LEN:\n    raise ValueError(\"replacement text out of range\")\nop = EditOp(target_id=eid, new_text=rewritten, new_refs=[ref])","handlingStrategy":"validation","validationCode":"from deeptutor.services.memory.ops import _MAX_TEXT_LEN\nnew_text = new_text.strip() if new_text else \"\"\nif not (1 <= len(new_text) <= _MAX_TEXT_LEN):\n    raise ValueError(\"replacement text out of range\")","typeGuard":"def is_valid_edit_text(text: str) -> bool:\n    return bool(text) and len(text) <= _MAX_TEXT_LEN","tryCatchPattern":"try:\n    ops.apply(doc, [op])\nexcept OpValidationError as e:\n    if e.args[0].startswith(\"edit: text length\"):\n        op = replace(op, new_text=op.new_text[:_MAX_TEXT_LEN])\n        ops.apply(doc, [op])\n    else:\n        raise","preventionTips":["Clamp LLM rewrites to _MAX_TEXT_LEN before building EditOp","Use DeleteOp for removals, never empty-string edits","Import limits from ops.py so constants stay in sync"],"tags":["validation","memory","ops","length-limit"],"backgroundTag":"payload-validation-failed","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}