{"record":{"id":"90904f06b816b3d6","repo":"astral-sh/ruff","slug":"tried-to-set-qos-of-thread-which-has-opted-out-of","errorCode":null,"errorMessage":"tried to set QoS of thread which has opted out of QoS (os error {errno})","messagePattern":"tried to set QoS of thread which has opted out of QoS \\(os error (.+?)\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/ty_server/src/server/schedule/thread/priority.rs","lineNumber":204,"sourceCode":"        #[expect(unsafe_code)]\n        let code = unsafe { libc::pthread_set_qos_class_self_np(c, 0) };\n\n        if code == 0 {\n            return;\n        }\n\n        #[expect(unsafe_code)]\n        let errno = unsafe { *libc::__error() };\n\n        match errno {\n            libc::EPERM => {\n                // This thread has been excluded from the QoS system\n                // due to a previous call to a function such as `pthread_setschedparam`\n                // which is incompatible with QoS.\n                //\n                // Panic instead of returning an error\n                // to maintain the invariant that we only use QoS APIs.\n                panic!(\"tried to set QoS of thread which has opted out of QoS (os error {errno})\")\n            }\n\n            libc::EINVAL => {\n                // This is returned if we pass something other than a qos_class_t\n                // to `pthread_set_qos_class_self_np`.\n                //\n                // This is impossible, so again panic.\n                unreachable!(\n                    \"invalid qos_class_t value was passed to pthread_set_qos_class_self_np\"\n                )\n            }\n\n            _ => {\n                // `pthread_set_qos_class_self_np`’s documentation\n                // does not mention any other errors.\n                unreachable!(\"`pthread_set_qos_class_self_np` returned unexpected error {errno}\")\n            }\n        }","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ty_server/src/server/schedule/thread/priority.rs#L186-L222","documentation":"On macOS, ty's scheduler sets the current thread's QoS class via `pthread_set_qos_class_self_np`. If the thread has opted out of the QoS system (e.g. a prior call to `pthread_setschedparam`), the call fails with EPERM, and ty panics because its design invariant is that it only ever uses QoS-compatible scheduling APIs. This is a macOS-only, internal-invariant panic.","triggerScenarios":"Running ty's LSP server on macOS inside a thread that previously called `pthread_setschedparam` or another manual scheduling API, so `set_current_thread_qos_class` receives errno EPERM.","commonSituations":"Embedding ty's server into another application that manages its own thread priorities; running within runtimes or wrappers that adjust thread scheduling; macOS-only regressions when hosting the server in foreign threads.","solutions":["Run the ty server on threads that have not had their scheduling configured via pthread_setschedparam or similar APIs.","Remove or defer manual thread-priority calls in the embedding code before starting ty's scheduler.","Use fresh default-priority threads for the server's worker pool."],"exampleFix":"// before: host code sets a fixed priority before starting ty\npthread_setschedparam(thread, SCHED_FIFO, &param);\nty_server::start(...);\n// after: start ty on an untouched thread, then customize elsewhere\nty_server::start(...);","handlingStrategy":"try-catch","validationCode":"// macOS: ensure the host thread has not opted out of QoS before hosting ty\nlet is_qos_compatible = std::env::var(\"CARGO_CFG_TARGET_OS\").as_deref() != Ok(\"macos\")\n    || !manual_scheduling_used;\nif !is_qos_compatible { /* run ty on a fresh default-priority thread */ }","typeGuard":null,"tryCatchPattern":"// The API panics, so guard by construction; catch at the thread boundary:\nstd::panic::catch_unwind(|| ty_server::run_on_current_thread())\n    .map_err(|_| \"thread opted out of QoS; re-run on a clean thread\")","preventionTips":["Never call pthread_setschedparam on threads that will host ty's scheduler.","Spawn dedicated default-priority threads for the server.","Use QoS APIs instead of legacy priority APIs on macOS."],"tags":["macos","qos","threads","panic","lsp"],"backgroundTag":"thread-qos-opt-out","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}