HKUDS/DeepTutor · error · ValueError

unknown layer {layer!r}

Error message

unknown layer {layer!r}

What it means

run_audit dispatches on the layer argument and only recognizes 'L2' and 'L3'. Any other string falls through to raise ValueError(f"unknown layer {layer!r}") after resetting the LLM selection token.

Source

Thrown at deeptutor/services/memory/consolidator/modes/audit.py:121

                key,  # type: ignore[arg-type]
                language=language,
                user_label=user_label,
                budget=budget if budget is not None else settings.audit.l2_budget,
                llm_selection=llm_selection,
                on_event=on_event,
                settings=settings,
            )
        if layer == "L3":
            return await _run_audit_l3(
                key,  # type: ignore[arg-type]
                language=language,
                user_label=user_label,
                budget=budget if budget is not None else settings.audit.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_audit_l2(
    surface: Surface,
    *,
    language: str,
    user_label: str,
    budget: int,
    llm_selection: dict | None,
    on_event: OnEvent | None,
    settings,
) -> AuditResult:
    l2_path = paths.l2_file(surface)

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Pass exactly 'L2' or 'L3' (uppercase, no whitespace)
  2. Normalize/case-fold and strip layer input at your API boundary before calling run_audit
  3. If a new layer is genuinely needed, add a branch in run_audit's dispatcher instead of a new string

Example fix

# before
result = await run_audit("l2", key, ...)
# after
result = await run_audit("L2", key, ...)
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

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

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

Try / catch

try:
    await run_audit(layer, key)
except ValueError as e:
    if "unknown layer" in str(e):
        layer = layer.strip().upper()
        if layer in ("L2", "L3"):
            await run_audit(layer, key)
        else:
            raise
    else:
        raise

Prevention

When it happens

Trigger: Calling run_audit with layer='l2' (lowercase), 'L1', 'l3', or any typo — the if/elif chain matches only the exact strings 'L2' and 'L3'.

Common situations: User-supplied or CLI-parsed layer strings with unexpected casing; a test passing a layer constant that changed after a rename (e.g. test_audit_l2_applies_replace_edit driving go()).

Related errors


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