{"record":{"id":"58626e862430e318","repo":"unslothai/unsloth","slug":"helper-llm-startup-pre-cache-must-be-true-or-false","errorCode":null,"errorMessage":"Helper LLM startup pre-cache must be true or false.","messagePattern":"Helper LLM startup pre-cache must be true or false\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/utils/helper_precache_settings.py","lineNumber":51,"sourceCode":"    \"\"\"Read the persisted startup pre-cache preference.\n\n    Missing or unreadable settings default to False so Unsloth startup never\n    performs optional network work unless the user explicitly opted in.\n    \"\"\"\n    try:\n        from storage.studio_db import get_app_setting\n        stored = get_app_setting(HELPER_PRECACHE_SETTING_KEY, None)\n    except Exception:\n        stored = None\n    parsed = _coerce_bool(stored)\n    return parsed if parsed is not None else DEFAULT_HELPER_PRECACHE_ENABLED\n\n\ndef set_helper_precache_enabled(value: Any) -> bool:\n    \"\"\"Persist whether Unsloth should pre-cache the Helper LLM at startup.\"\"\"\n    parsed = _coerce_bool(value)\n    if parsed is None:\n        raise ValueError(\"Helper LLM startup pre-cache must be true or false.\")\n\n    from storage.studio_db import upsert_app_settings\n\n    upsert_app_settings({HELPER_PRECACHE_SETTING_KEY: parsed})\n    return parsed\n\n\ndef should_preload_helper_on_startup() -> bool:\n    \"\"\"Gate the startup pre-cache thread.\n\n    The persisted setting is opt-in and the existing broad disable env var wins.\n    Explicit AI Assist calls do not use this gate; they remain user-triggered.\n    \"\"\"\n    return get_helper_precache_enabled() and not helper_model_disabled_by_env()\n","sourceCodeStart":33,"sourceCodeEnd":66,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/helper_precache_settings.py#L33-L66","documentation":"Raised by set_helper_precache_enabled when the value cannot be coerced to a boolean by _coerce_bool. The setting persists to the studio DB (upsert_app_settings) and gates an opt-in startup pre-cache thread for the Helper LLM; only unambiguously boolean-coercible input is accepted. The broad disable env var and explicit AI Assist calls bypass this gate entirely.","triggerScenarios":"Calling set_helper_precache_enabled with values _coerce_bool rejects — e.g. 'maybe', 2, [], None, or 'on'/'off' depending on the coercion rules — rather than True/False, 1/0, or 'true'/'false'.","commonSituations":"Settings UI posting a checkbox tri-state or raw string; API clients sending JSON numbers other than 0/1; scripts passing os.getenv(...) raw (None when the var is unset).","solutions":["Pass a real boolean: set_helper_precache_enabled(True) / (False).","If the value comes from an env var or UI string, normalize it first (e.g. value in ('1','true','yes') → True).","Handle unset optional values before calling: if raw is None, skip the call rather than passing None.","Check _coerce_bool's accepted forms if you must send strings."],"exampleFix":"# before\nset_helper_precache_enabled(os.getenv(\"HELPER_PRECACHE\"))  # None when unset -> ValueError\n\n# after\nraw = os.getenv(\"HELPER_PRECACHE\")\nif raw is not None:\n    set_helper_precache_enabled(raw.lower() in (\"1\", \"true\", \"yes\"))","handlingStrategy":"validation","validationCode":"def to_bool_or_none(v):\n    if isinstance(v, bool):\n        return v\n    if isinstance(v, (int, float)) and v in (0, 1):\n        return bool(v)\n    if isinstance(v, str) and v.strip().lower() in (\"true\", \"1\", \"yes\", \"false\", \"0\", \"no\"):\n        return v.strip().lower() in (\"true\", \"1\", \"yes\")\n    return None\n\n# guard: parsed = to_bool_or_none(raw); assert parsed is not None","typeGuard":"def is_coercible_bool(value) -> bool:\n    if isinstance(value, bool):\n        return True\n    if isinstance(value, int):\n        return value in (0, 1)\n    if isinstance(value, str):\n        return value.strip().lower() in (\"true\", \"false\", \"1\", \"0\", \"yes\", \"no\")\n    return False","tryCatchPattern":null,"preventionTips":["Always send real JSON booleans to settings APIs.","Never forward raw os.getenv() results (None when unset) into setters.","Normalize checkbox/tri-state UI values before persistence.","Remember the disable env var overrides this setting and explicit AI Assist calls bypass the gate."],"tags":["settings","boolean-coercion","config","validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}