{"record":{"id":"c98e04270cb6b0a6","repo":"HKUDS/DeepTutor","slug":"add-malformed-ref-ref-r","errorCode":null,"errorMessage":"add: malformed ref {ref!r}","messagePattern":"add: malformed ref (.+?)","errorType":"validation","errorClass":"OpValidationError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/memory/ops.py","lineNumber":84,"sourceCode":"\n\ndef _validate(doc: Document, ops: list[Op]) -> None:\n    edits: set[str] = set()\n    deletes: set[str] = set()\n\n    for op in ops:\n        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                )","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/memory/ops.py#L66-L102","documentation":"OpValidationError raised in _validate when one of an AddOp's refs fails is_valid_ref. Refs use a constrained grammar (a validated reference format identifying source messages/spans), and any string outside that grammar is rejected so entries never carry unparseable provenance.","triggerScenarios":"AddOp(..., refs=[\"some arbitrary string\"]) where the string doesn't match the ref format — e.g. passing raw URLs, plain message text, 'msg: ' with an invalid id, or a ref built by string concatenation with a typo.","commonSituations":"LLM free-typing refs in a tool call; constructing refs from ids containing whitespace/invalid characters; version drift where the ref grammar changed but callers still emit the old format.","solutions":["Build refs only with the library's own helper/constructor for refs (or copy the exact format is_valid_ref enforces — read its implementation in ops.py)","Validate each ref with is_valid_ref before constructing the op and drop/repair failures","If ids are user/LLM supplied, sanitize them (strip, charset-check) before embedding in a ref"],"exampleFix":"# before\nop = AddOp(text=note, section=\"facts\", refs=[f\"source {msg_id}\"])\n\n# after\nfrom deeptutor.services.memory.ops import is_valid_ref\nref = f\"msg:{msg_id}\"\nassert is_valid_ref(ref), f\"bad ref: {ref}\"\nop = AddOp(text=note, section=\"facts\", refs=[ref])","handlingStrategy":"validation","validationCode":"from deeptutor.services.memory.ops import is_valid_ref\nrefs = [r for r in raw_refs if is_valid_ref(r)]\nif not refs:\n    raise ValueError(\"no valid refs after filtering\")","typeGuard":"def refs_are_valid(refs) -> bool:\n    return bool(refs) and all(is_valid_ref(r) for r in refs)","tryCatchPattern":"try:\n    ops.apply(doc, [op])\nexcept OpValidationError as e:\n    if \"malformed ref\" in str(e):\n        op = replace(op, refs=[make_ref(source)])\n        ops.apply(doc, [op])\n    else:\n        raise","preventionTips":["Build refs only via the library's ref format/helper","Filter refs through is_valid_ref at the boundary","Never let free-form LLM text become a ref verbatim"],"tags":["validation","memory","ops","ref-format"],"backgroundTag":"payload-validation-failed","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}