{"record":{"id":"34a13c878c967964","repo":"mudler/LocalAI","slug":"name-must-be-true-or-false","errorCode":null,"errorMessage":"{name} must be true or false","messagePattern":"(.+?) must be true or false","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/python/longcat-video/longcat_utils.py","lineNumber":90,"sourceCode":"    LocalAI injects serving defaults (e.g. the llama.cpp cache_reuse / parallel\n    options) onto every model config regardless of backend. A backend should\n    tolerate options it does not understand rather than refuse to load, matching\n    the other LocalAI Python backends; the caller logs the ignored keys.\n\n    Returns (kept, ignored) where kept preserves the known entries and ignored is\n    the sorted list of dropped keys.\n    \"\"\"\n    ignored = sorted(key for key in options if key not in known)\n    kept = {key: value for key, value in options.items() if key in known}\n    return kept, ignored\n\n\ndef require_bool(value, name):\n    if isinstance(value, bool):\n        return value\n    if isinstance(value, str) and value.lower() in {\"true\", \"false\"}:\n        return value.lower() == \"true\"\n    raise ValueError(f\"{name} must be true or false\")\n\n\ndef require_int(value, name, minimum=None, maximum=None):\n    try:\n        parsed = int(value)\n    except (TypeError, ValueError) as err:\n        raise ValueError(f\"{name} must be an integer\") from err\n    if minimum is not None and parsed < minimum:\n        raise ValueError(f\"{name} must be at least {minimum}\")\n    if maximum is not None and parsed > maximum:\n        raise ValueError(f\"{name} must be at most {maximum}\")\n    return parsed\n\n\ndef require_float(value, name, minimum=None, maximum=None):\n    try:\n        parsed = float(value)\n    except (TypeError, ValueError) as err:","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/python/longcat-video/longcat_utils.py#L72-L108","documentation":"ValueError from require_bool() in longcat_utils.py: model/request option values that are supposed to be boolean must be either an actual Python bool or the strings 'true'/'false' (case-insensitive). Anything else — '1', 'yes', 0, None, 'True ' with odd casing is fine but 'TRUE ' with whitespace, 'on', integers — is rejected with '{name} must be true or false', where name identifies the offending option (e.g. use_distill, use_int8).","triggerScenarios":"Setting use_int8: 1 or use_distill: \"yes\" in YAML model options; passing 0/1 ints from generated config tooling; values like 'on'/'off' from environment-style config.","commonSituations":"YAML auto-parses yes/no to bool (fine) but JSON configs with 1/0 integers; templates rendering booleans as strings like 'True' works, but 'true ' with trailing whitespace or 'enabled' fails.","solutions":["Use literal true/false booleans in YAML/model options (they parse to Python bool)","If values come from string sources, normalize to 'true'/'false' (lowercased, trimmed) before passing","Identify the offending option from the name in the message and fix just that key"],"exampleFix":"# before\noptions:\n  use_distill: 1\n  use_int8: \"yes\"\n\n# after\noptions:\n  use_distill: true\n  use_int8: false","handlingStrategy":"validation","validationCode":"def coerce_bool(value, name: str) -> bool:\n    if isinstance(value, bool):\n        return value\n    if isinstance(value, str) and value.strip().lower() in {\"true\", \"false\"}:\n        return value.strip().lower() == \"true\"\n    raise ValueError(f\"{name} must be true or false, got {value!r}\")\n\noptions = {k: coerce_bool(v, k) if k in BOOL_KEYS else v for k, v in options.items()}","typeGuard":"def is_bool_like(value) -> bool:\n    return isinstance(value, bool) or (isinstance(value, str) and value.strip().lower() in {\"true\", \"false\"})","tryCatchPattern":"try:\n    stub.LoadModel(opts)\nexcept grpc.RpcError as e:\n    if \"must be true or false\" in (e.details() or \"\"):\n        name = e.details().split()[0]  # offending option name\n        opts[\"options\"][name] = bool(opts[\"options\"][name])  # coerce and retry\n        stub.LoadModel(opts)\n    else:\n        raise","preventionTips":["Normalize all boolean options through a coerce_bool helper before they reach the backend","Ban 0/1 integers and yes/no strings for booleans in your config linting"],"tags":["python","longcat-video","configuration","validation"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}