HKUDS/DeepTutor · error · ValueError

preferences.md is not auto-consolidated

Error message

preferences.md is not auto-consolidated

What it means

The memory consolidator deliberately excludes the 'preferences' L3 slot from automatic consolidation, because preferences.md is curated manually. Any attempt to run consolidate_l3 (or update_l3) with slot='preferences' raises this ValueError by design.

Source

Thrown at deeptutor/services/memory/consolidator/modes/_shims.py:80

        language=language,
        user_label=user_label,
        on_event=on_event,
    )
    if not apply_ops:
        _rollback_new_entries("L2", surface, result.new_entry_ids)
    return _to_consolidate_result(result)


async def consolidate_l3(
    slot: L3Slot,
    *,
    language: str = "en",
    user_label: str = "anonymous",
    on_event: OnEvent | None = None,
    apply_ops: bool = True,
) -> ConsolidateResult:
    if slot == "preferences":
        raise ValueError("preferences.md is not auto-consolidated")
    result = await run_update(
        "L3",
        slot,
        language=language,
        user_label=user_label,
        on_event=on_event,
    )
    if not apply_ops:
        _rollback_new_entries("L3", slot, result.new_entry_ids)
    return _to_consolidate_result(result)


def _to_consolidate_result(result: UpdateResult) -> ConsolidateResult:
    reason = (
        "no new input"
        if result.no_new_input
        else f"applied via chunk-update ({result.facts_added} added)"
    )

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Skip the 'preferences' slot in any batch loop over L3 slots
  2. Use the dedicated preferences update API/manual editing path if you need to change preferences.md
  3. Filter the slot list before consolidating: slots = [s for s in slots if s != 'preferences']

Example fix

# before
for slot in all_l3_slots:
    await consolidate_l3(slot)
# after
for slot in all_l3_slots:
    if slot != "preferences":
        await consolidate_l3(slot)
Defensive patterns

Strategy: validation

Validate before calling

AUTO_CONSOLIDABLE = lambda slot: slot != "preferences"

for slot in l3_slots:
    if AUTO_CONSOLIDABLE(slot):
        await consolidate_l3(slot)

Type guard

def is_auto_consolidated(slot: str) -> bool:
    """Type/narrowing guard: True if consolidate_l3 accepts this slot."""
    return slot != "preferences"

Try / catch

try:
    await consolidate_l3(slot)
except ValueError as e:
    if "not auto-consolidated" in str(e):
        continue  # preferences slot; skip
    raise

Prevention

When it happens

Trigger: Calling consolidate_l3(slot="preferences") or update_l3("L3", "preferences") — the guard fires immediately, before any LLM work.

Common situations: Looping over all L3 slots generically (e.g. for slot in list_l3_slots(): consolidate_l3(slot)) without excluding 'preferences'; refactoring code that previously treated preferences like any other slot.

Related errors


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