HKUDS/DeepTutor · error · OpValidationError
edit: target_id {op.target_id} not found
Error message
edit: target_id {op.target_id} not found What it means
OpValidationError raised in _validate when an EditOp's target_id is well-formed but doc.find(target_id) returns None — the entry being edited no longer (or never) exists in this document snapshot. Validation runs against the specific Document passed to ops.apply, so stale ids from an older version of the document are caught here, before any write.
Source
Thrown at deeptutor/services/memory/ops.py:89
for op in ops:
if isinstance(op, AddOp):
if not op.text or len(op.text) > _MAX_TEXT_LEN:
raise OpValidationError(
f"add: text length must be 1..{_MAX_TEXT_LEN} (got {len(op.text)})"
)
if not op.section or len(op.section) > _MAX_SECTION_LEN:
raise OpValidationError(f"add: invalid section {op.section!r}")
if not op.refs:
raise OpValidationError("add: refs must be non-empty")
for ref in op.refs:
if not is_valid_ref(ref):
raise OpValidationError(f"add: malformed ref {ref!r}")
elif isinstance(op, EditOp):
if not is_entry_id(op.target_id):
raise OpValidationError(f"edit: malformed target_id {op.target_id!r}")
if doc.find(op.target_id) is None:
raise OpValidationError(f"edit: target_id {op.target_id} not found")
if not op.new_text or len(op.new_text) > _MAX_TEXT_LEN:
raise OpValidationError(
f"edit: text length must be 1..{_MAX_TEXT_LEN} (got {len(op.new_text)})"
)
if not op.new_refs:
raise OpValidationError("edit: refs must be non-empty")
for ref in op.new_refs:
if not is_valid_ref(ref):
raise OpValidationError(f"edit: malformed ref {ref!r}")
if op.target_id in deletes:
raise OpValidationError(
f"batch conflict: edit and delete on same id {op.target_id}"
)
edits.add(op.target_id)
elif isinstance(op, DeleteOp):
if not is_entry_id(op.target_id):
raise OpValidationError(f"delete: malformed target_id {op.target_id!r}")
if doc.find(op.target_id) is None:View on GitHub (pinned to 3e82f13042)
Solutions
- Re-read the document and re-resolve the entry id immediately before applying the edit; retry with the fresh id if the entry still exists
- If the entry is gone, convert the edit into an AddOp of the new text instead of failing
- Serialize memory writes (or use the run manager) so consolidation can't remove entries between read and apply
Example fix
# before
op = EditOp(target_id=stale_id, new_text=new_note, new_refs=[ref])
result = ops.apply(old_doc, [op])
# after
doc = load_doc() # fresh snapshot
if doc.find(stale_id) is None:
op = AddOp(text=new_note, section=last_known_section, refs=[ref])
else:
op = EditOp(target_id=stale_id, new_text=new_note, new_refs=[ref])
result = ops.apply(doc, [op]) Defensive patterns
Strategy: retry
Validate before calling
doc = load_doc() # fresh snapshot
if doc.find(target_id) is None:
target_id = reresolve_entry(doc, old_text_matcher)
if target_id is None:
op = AddOp(text=new_text, section=section, refs=new_refs) Type guard
def target_exists(doc, target_id: str) -> bool:
return doc.find(target_id) is not None Try / catch
try:
ops.apply(doc, [op])
except OpValidationError as e:
if "not found" in str(e):
doc = load_doc()
if doc.find(op.target_id) is not None:
ops.apply(doc, [op]) # retry on fresh snapshot
else:
ops.apply(doc, [to_add_op(op)]) # degrade to add
else:
raise Prevention
- Re-read the document right before applying edits
- Fall back to AddOp when the entry disappeared
- Serialize writes vs consolidation to avoid stale snapshots
When it happens
Trigger: Editing based on a stale document: the entry was deleted or consolidated away after the caller read the doc, so the id isn't in the current Document passed to apply. Also passing the wrong Document (different KB/slot) to apply.
Common situations: Read-modify-write races with the consolidator or another session; long-lived cached entry lists in an agent loop; LLM editing an entry id from an earlier turn after memory changed; tests reusing fixtures across mutations.
Related errors
- add: text length must be 1..{_MAX_TEXT_LEN} (got {len(op.tex
- add: invalid section {op.section!r}
- add: refs must be non-empty
- add: malformed ref {ref!r}
- edit: malformed target_id {op.target_id!r}
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/93347660b73b5aaa.
Report an issue: GitHub.