{"record":{"id":"15546fb874605369","repo":"unslothai/unsloth","slug":"is-enabled-must-be-true-or-false","errorCode":null,"errorMessage":"is_enabled must be true or false","messagePattern":"is_enabled must be true or false","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"studio/backend/routes/mcp_servers.py","lineNumber":192,"sourceCode":"\n\ndef _changes_from_payload(payload: McpServerUpdate) -> dict:\n    sent = payload.model_fields_set\n    changes: dict = {}\n\n    if \"display_name\" in sent:\n        name = (payload.display_name or \"\").strip()\n        if not name:\n            raise HTTPException(status_code = 400, detail = \"display_name must not be empty\")\n        changes[\"display_name\"] = name\n    if \"url\" in sent:\n        changes[\"url\"] = _validate_url(payload.url or \"\")\n    if \"headers\" in sent:\n        headers = _normalize_headers(payload.headers)\n        changes[\"headers_json\"] = json.dumps(headers) if headers else None\n    if \"is_enabled\" in sent:\n        if payload.is_enabled is None:\n            raise HTTPException(status_code = 400, detail = \"is_enabled must be true or false\")\n        changes[\"is_enabled\"] = payload.is_enabled\n    if \"use_oauth\" in sent:\n        if payload.use_oauth is None:\n            raise HTTPException(status_code = 400, detail = \"use_oauth must be true or false\")\n        changes[\"use_oauth\"] = payload.use_oauth\n    # stdio is OAuth-less: drop a stale OAuth flag when switching to a command.\n    if \"url\" in changes and is_stdio(changes[\"url\"]):\n        changes[\"use_oauth\"] = False\n    return changes\n\n\n@router.put(\"/{server_id}\", response_model = McpServerResponse)\nasync def update_mcp_server(\n    server_id: str,\n    payload: McpServerUpdate,\n    current_subject: str = Depends(get_current_subject),\n    via_api_key: ViaApiKey = False,\n):","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/routes/mcp_servers.py#L174-L210","documentation":"400 from _changes_from_payload when the update payload explicitly includes is_enabled but its value is null. Because is_enabled is a tri-state in the update model (absent = don't change, true/false = set), null is neither and is rejected — the column is NOT NULL semantically.","triggerScenarios":"PUT /{server_id} with {\"is_enabled\": null} in the body (key present, value null).","commonSituations":"JS clients whose state uses null for unchecked/unknown toggles; spreading a partially-filled form object into the PUT body.","solutions":["Send true or false, e.g. {\"is_enabled\": false} to disable the server.","Omit the key when the toggle state shouldn't change.","Normalize client state to booleans before sending (Boolean(value) or !!value)."],"exampleFix":"// before\nawait api.put(`/api/mcp-servers/${id}`, {is_enabled: toggled ? true : null});\n\n// after\nawait api.put(`/api/mcp-servers/${id}`, {is_enabled: !!toggled});","handlingStrategy":"type-guard","validationCode":"if ('is_enabled' in payload) {\n  if (typeof payload.is_enabled !== 'boolean') throw new Error('is_enabled must be true or false');\n}","typeGuard":"const isBoolOrNull = (v) => v === null || typeof v === 'boolean';\nfunction validEnabledUpdate(p) { return !('is_enabled' in p) || typeof p.is_enabled === 'boolean'; }","tryCatchPattern":null,"preventionTips":["Coerce toggles to real booleans (!!) before sending.","Omit the key rather than sending null to mean 'unchanged'."],"tags":["mcp","validation","http-400","boolean"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}