{"record":{"id":"08f5d0b7c6d82e05","repo":"unslothai/unsloth","slug":"keep-model-in-gpu-memory-must-be-true-or-false","errorCode":null,"errorMessage":"Keep model in GPU memory must be true or false.","messagePattern":"Keep model in GPU memory must be true or false\\.","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"studio/backend/utils/model_memory_settings.py","lineNumber":146,"sourceCode":"    pair = (get_keep_resident(), get_no_ram_reserve())\n    for _attempt in range(_MAX_REREADS):\n        before = _pair_generations()\n        pair = (get_keep_resident(), get_no_ram_reserve())\n        if _pair_generations() == before:\n            return pair\n    return pair\n\n\ndef set_model_memory_settings(\n    keep_resident: Any = None, no_ram_reserve: Any = None\n) -> tuple[bool, bool]:\n    \"\"\"One-transaction write; ``None`` leaves a stored value untouched.\"\"\"\n    updates: dict[str, bool] = {}\n\n    if keep_resident is not None:\n        parsed = _coerce_bool(keep_resident)\n        if parsed is None:\n            raise ValueError(\"Keep model in GPU memory must be true or false.\")\n        updates[KEEP_RESIDENT_SETTING_KEY] = parsed\n\n    if no_ram_reserve is not None:\n        parsed = _coerce_bool(no_ram_reserve)\n        if parsed is None:\n            raise ValueError(\"Do not reserve system RAM must be true or false.\")\n        updates[NO_RAM_RESERVE_SETTING_KEY] = parsed\n\n    if updates:\n        from storage.studio_db import upsert_app_settings\n        upsert_app_settings(updates)\n        _invalidate(*updates)\n\n    return get_keep_resident(), get_no_ram_reserve()\n\n\ndef memlock_limit_bytes() -> Optional[int]:\n    \"\"\"Soft RLIMIT_MEMLOCK, or None when unlimited or unavailable.","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/model_memory_settings.py#L128-L164","documentation":"set_model_memory_settings() coerces the keep_resident argument with _coerce_bool(); if the value is non-None but not recognizable as a boolean (not bool, not 0/1, not 'true'/'false'-style strings), _coerce_bool returns None and this ValueError fires. The message names the UI toggle ('Keep model in GPU memory') the API field maps to.","triggerScenarios":"set_model_memory_settings(keep_resident='yes'), keep_resident=2, keep_resident='on', or keep_resident=[] — anything truthy-looking but outside _coerce_bool's accepted forms. Passing None is the sanctioned 'leave unchanged' path and never raises.","commonSituations":"A frontend sending checkbox tri-state values ('yes'/'no'), sending integers other than 0/1, or a client serializing booleans as strings without normalization; API consumers guessing the payload shape.","solutions":["Send an actual JSON boolean: set_model_memory_settings(keep_resident=True)","If the value is a string, normalize to 0/1 or 'true'/'false' before calling (check _coerce_bool's accepted forms)","Omit the field (or pass None) when you do not intend to change it"],"exampleFix":"# before\nset_model_memory_settings(keep_resident='yes')\n# ValueError: Keep model in GPU memory must be true or false.\n\n# after\nset_model_memory_settings(keep_resident=True)","handlingStrategy":"type-guard","validationCode":"def is_bool_like(v) -> bool:\n    return v is None or isinstance(v, bool) or v in (0, 1) or str(v).strip().lower() in ('true', 'false')\n\nif not is_bool_like(payload.get('keep_resident')):\n    return 400 'keep_resident must be a boolean'","typeGuard":"def coerce_bool_or_none(v):\n    if v is None or isinstance(v, bool):\n        return v\n    if isinstance(v, int) and v in (0, 1):\n        return bool(v)\n    if isinstance(v, str) and v.strip().lower() in ('true', 'false'):\n        return v.strip().lower() == 'true'\n    return None  # caller rejects","tryCatchPattern":"try:\n    set_model_memory_settings(keep_resident=v)\nexcept ValueError as e:\n    return 422 {'detail': str(e)}","preventionTips":["Send real JSON booleans from clients; normalize checkbox values at the API boundary","Pass None (or omit) to leave a setting unchanged"],"tags":["settings","boolean-coercion","gpu-memory","api-validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}