HKUDS/DeepTutor · error · ValueError

unknown layer {layer!r}

Error message

unknown layer {layer!r}

What it means

run_update dispatches consolidation per layer and supports only 'L2' and 'L3'. Any other layer string falls through to ValueError after the finally block resets the LLM selection token; both consolidate_l2 and consolidate_l3 delegate here.

Source

Thrown at deeptutor/services/memory/consolidator/modes/update.py:132

                key,  # type: ignore[arg-type]
                language=language,
                user_label=user_label,
                budget=budget if budget is not None else settings.update.l2_budget,
                llm_selection=llm_selection,
                on_event=on_event,
                settings=settings,
            )
        if layer == "L3":
            return await _run_update_l3(
                key,  # type: ignore[arg-type]
                language=language,
                user_label=user_label,
                budget=budget if budget is not None else settings.update.l3_budget,
                llm_selection=llm_selection,
                on_event=on_event,
                settings=settings,
            )
        raise ValueError(f"unknown layer {layer!r}")
    finally:
        reset_llm_selection(token)


# ── L2 ──────────────────────────────────────────────────────────────────


async def _run_update_l2(
    surface: Surface,
    *,
    language: str,
    user_label: str,
    budget: int,
    llm_selection: dict | None,
    on_event: OnEvent | None,
    settings,
) -> UpdateResult:
    meta = load_l2_meta(surface)

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Pass exactly 'L2' or 'L3'
  2. Normalize and validate the layer string at the call site before invoking run_update
  3. Centralize layer names in a Literal type or enum used by all consolidator modes

Example fix

# before
result = await run_update("l3", slot, ...)
# after
result = await run_update("L3", slot, ...)
Defensive patterns

Strategy: type-guard

Validate before calling

if layer not in ("L2", "L3"):
    raise ValueError(f"layer must be 'L2' or 'L3', got {layer!r}")

Type guard

from typing import Literal, TypeGuard

Layer = Literal["L2", "L3"]

def is_layer(v: object) -> TypeGuard[Layer]:
    return isinstance(v, str) and v in ("L2", "L3")

Try / catch

try:
    await run_update(layer, slot)
except ValueError as e:
    if "unknown layer" in str(e):
        return  # or normalize and retry
    raise

Prevention

When it happens

Trigger: Calling run_update (directly or via consolidate_l2/consolidate_l3 wrappers) with a layer argument that is not exactly 'L2' or 'L3' — e.g. 'l2', 'L1', or a value from unvalidated config.

Common situations: Programmatic loops over layer names built from f-strings or user input; casing/format drift between the caller's constants and the consolidator's expected literals.

Related errors


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