{"record":{"id":"69461bcc6c14853f","repo":"unslothai/unsloth","slug":"keep-kv-on-idle-unload-must-be-true-or-false","errorCode":null,"errorMessage":"Keep KV on idle unload must be true or false.","messagePattern":"Keep KV on idle unload must be true or false\\.","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"studio/backend/utils/openai_auto_switch_settings.py","lineNumber":316,"sourceCode":"            raise ValueError(\n                f\"Auto-unload idle seconds must be 0 (off) or at least \"\n                f\"{MIN_AUTO_UNLOAD_IDLE_SECONDS}.\"\n            )\n    parsed_media_idle = None\n    if media_idle_seconds is not None:\n        parsed_media_idle = _coerce_int(media_idle_seconds)\n        if parsed_media_idle is None:\n            raise ValueError(\"Media auto-unload idle seconds must be a non-negative integer.\")\n        if 0 < parsed_media_idle < MIN_AUTO_UNLOAD_IDLE_SECONDS:\n            raise ValueError(\n                f\"Media auto-unload idle seconds must be 0 (off) or at least \"\n                f\"{MIN_AUTO_UNLOAD_IDLE_SECONDS}.\"\n            )\n    parsed_keep_kv = None\n    if keep_kv is not None:\n        parsed_keep_kv = _coerce_bool(keep_kv)\n        if parsed_keep_kv is None:\n            raise ValueError(\"Keep KV on idle unload must be true or false.\")\n    parsed_auto_download = None\n    if auto_download is not None:\n        parsed_auto_download = _coerce_bool(auto_download)\n        if parsed_auto_download is None:\n            raise ValueError(\"Auto-download missing models must be true or false.\")\n    parsed_api_only = None\n    if api_only is not None:\n        parsed_api_only = _coerce_bool(api_only)\n        if parsed_api_only is None:\n            raise ValueError(\"Auto-unload API-loaded only must be true or false.\")\n    from storage.studio_db import upsert_app_settings\n\n    updates: dict[str, Any] = {OPENAI_AUTO_SWITCH_SETTING_KEY: parsed_enabled}\n    if parsed_idle is not None:\n        updates[AUTO_UNLOAD_IDLE_SETTING_KEY] = parsed_idle\n    if parsed_media_idle is not None:\n        updates[MEDIA_AUTO_UNLOAD_IDLE_SETTING_KEY] = parsed_media_idle\n    if parsed_keep_kv is not None:","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/openai_auto_switch_settings.py#L298-L334","documentation":"Raised by set_openai_auto_switch in openai_auto_switch_settings.py:315-317 when keep_kv is provided and _coerce_bool returns None. Accepted: real bools and strings 1/true/yes/on, 0/false/no/off (case-insensitive). Integers 1/0 and any other token (\"keep\", \"y\", \"checked\") are rejected.","triggerScenarios":"set_openai_auto_switch(enabled=True, keep_kv=1) from a checkbox that yields ints; keep_kv=\"keep\"; keep_kv=[True]. Python None is allowed (leave stored value).","commonSituations":"HTML checkbox handlers sending \"1\"/\"0\" as ints after JSON parsing; API clients normalizing booleans to ints; truthy strings from environment variables like \"yes please\".","solutions":["Pass a real bool (keep_kv=True)","Normalize checkbox ints to bool: bool(int(raw)) before calling","Whitelist the coercion tokens in your validation layer","Omit the argument to leave the stored setting unchanged"],"exampleFix":"# before\nset_openai_auto_switch(enabled=True, keep_kv=1)\n\n# after\nset_openai_auto_switch(enabled=True, keep_kv=True)","handlingStrategy":"validation","validationCode":"def to_bool(v) -> bool | None:\n    if isinstance(v, bool):\n        return v\n    if isinstance(v, str):\n        n = v.strip().lower()\n        if n in {\"1\", \"true\", \"yes\", \"on\"}: return True\n        if n in {\"0\", \"false\", \"no\", \"off\"}: return False\n    return None\n\nif keep_kv is not None and to_bool(keep_kv) is None:\n    raise HTTPException(400, \"keep_kv must be a boolean\")","typeGuard":"def is_bool_like(v: object) -> bool:\n    return isinstance(v, bool) or (\n        isinstance(v, str) and v.strip().lower() in {\"1\",\"true\",\"yes\",\"on\",\"0\",\"false\",\"no\",\"off\"}\n    )","tryCatchPattern":"try:\n    set_openai_auto_switch(enabled=True, keep_kv=keep_kv)\nexcept ValueError as exc:\n    raise HTTPException(400, str(exc)) from exc","preventionTips":["Convert checkbox 1/0 to bool at the form boundary","Send JSON true/false from API clients","Omit optional flags instead of passing 0/1 ints"],"tags":["settings","validation","boolean-coercion"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}