HKUDS/DeepTutor · error · OpValidationError

add: malformed ref {ref!r}

Error message

add: malformed ref {ref!r}

What it means

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.

Source

Thrown at deeptutor/services/memory/ops.py:84


def _validate(doc: Document, ops: list[Op]) -> None:
    edits: set[str] = set()
    deletes: set[str] = set()

    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}"
                )

View on GitHub (pinned to 3e82f13042)

Solutions

  1. 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)
  2. Validate each ref with is_valid_ref before constructing the op and drop/repair failures
  3. If ids are user/LLM supplied, sanitize them (strip, charset-check) before embedding in a ref

Example fix

# before
op = AddOp(text=note, section="facts", refs=[f"source {msg_id}"])

# after
from deeptutor.services.memory.ops import is_valid_ref
ref = f"msg:{msg_id}"
assert is_valid_ref(ref), f"bad ref: {ref}"
op = AddOp(text=note, section="facts", refs=[ref])
Defensive patterns

Strategy: validation

Validate before calling

from deeptutor.services.memory.ops import is_valid_ref
refs = [r for r in raw_refs if is_valid_ref(r)]
if not refs:
    raise ValueError("no valid refs after filtering")

Type guard

def refs_are_valid(refs) -> bool:
    return bool(refs) and all(is_valid_ref(r) for r in refs)

Try / catch

try:
    ops.apply(doc, [op])
except OpValidationError as e:
    if "malformed ref" in str(e):
        op = replace(op, refs=[make_ref(source)])
        ops.apply(doc, [op])
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/c98e04270cb6b0a6. Report an issue: GitHub.