{"record":{"id":"15f51e134d5c4ef6","repo":"HKUDS/DeepTutor","slug":"unknown-layer-layer-r","errorCode":null,"errorMessage":"unknown layer {layer!r}","messagePattern":"unknown layer (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/memory/consolidator/modes/audit.py","lineNumber":121,"sourceCode":"                key,  # type: ignore[arg-type]\n                language=language,\n                user_label=user_label,\n                budget=budget if budget is not None else settings.audit.l2_budget,\n                llm_selection=llm_selection,\n                on_event=on_event,\n                settings=settings,\n            )\n        if layer == \"L3\":\n            return await _run_audit_l3(\n                key,  # type: ignore[arg-type]\n                language=language,\n                user_label=user_label,\n                budget=budget if budget is not None else settings.audit.l3_budget,\n                llm_selection=llm_selection,\n                on_event=on_event,\n                settings=settings,\n            )\n        raise ValueError(f\"unknown layer {layer!r}\")\n    finally:\n        reset_llm_selection(token)\n\n\n# ── L2 ──────────────────────────────────────────────────────────────────\n\n\nasync def _run_audit_l2(\n    surface: Surface,\n    *,\n    language: str,\n    user_label: str,\n    budget: int,\n    llm_selection: dict | None,\n    on_event: OnEvent | None,\n    settings,\n) -> AuditResult:\n    l2_path = paths.l2_file(surface)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/memory/consolidator/modes/audit.py#L103-L139","documentation":"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.","triggerScenarios":"Calling run_audit with layer='l2' (lowercase), 'L1', 'l3', or any typo — the if/elif chain matches only the exact strings 'L2' and 'L3'.","commonSituations":"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()).","solutions":["Pass exactly 'L2' or 'L3' (uppercase, no whitespace)","Normalize/case-fold and strip layer input at your API boundary before calling run_audit","If a new layer is genuinely needed, add a branch in run_audit's dispatcher instead of a new string"],"exampleFix":"# before\nresult = await run_audit(\"l2\", key, ...)\n# after\nresult = await run_audit(\"L2\", key, ...)","handlingStrategy":"type-guard","validationCode":"if layer not in {\"L2\", \"L3\"}:\n    raise ValueError(f\"layer must be 'L2' or 'L3', got {layer!r}\")","typeGuard":"from typing import Literal\n\nLayer = Literal[\"L2\", \"L3\"]\n\ndef is_layer(v: str) -> TypeGuard[Layer]:\n    return v in (\"L2\", \"L3\")","tryCatchPattern":"try:\n    await run_audit(layer, key)\nexcept ValueError as e:\n    if \"unknown layer\" in str(e):\n        layer = layer.strip().upper()\n        if layer in (\"L2\", \"L3\"):\n            await run_audit(layer, key)\n        else:\n            raise\n    else:\n        raise","preventionTips":["Normalize layer strings (strip().upper()) at API boundaries","Type layer parameters as Literal['L2','L3']"],"tags":["memory","audit","dispatch","argument-validation"],"backgroundTag":"unknown-layer-argument","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}