astral-sh/ruff · critical
tried to set QoS of thread which has opted out of QoS (os er
Error message
tried to set QoS of thread which has opted out of QoS (os error {errno}) What it means
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.
Source
Thrown at crates/ty_server/src/server/schedule/thread/priority.rs:204
#[expect(unsafe_code)]
let code = unsafe { libc::pthread_set_qos_class_self_np(c, 0) };
if code == 0 {
return;
}
#[expect(unsafe_code)]
let errno = unsafe { *libc::__error() };
match errno {
libc::EPERM => {
// This thread has been excluded from the QoS system
// due to a previous call to a function such as `pthread_setschedparam`
// which is incompatible with QoS.
//
// Panic instead of returning an error
// to maintain the invariant that we only use QoS APIs.
panic!("tried to set QoS of thread which has opted out of QoS (os error {errno})")
}
libc::EINVAL => {
// This is returned if we pass something other than a qos_class_t
// to `pthread_set_qos_class_self_np`.
//
// This is impossible, so again panic.
unreachable!(
"invalid qos_class_t value was passed to pthread_set_qos_class_self_np"
)
}
_ => {
// `pthread_set_qos_class_self_np`’s documentation
// does not mention any other errors.
unreachable!("`pthread_set_qos_class_self_np` returned unexpected error {errno}")
}
}View on GitHub (pinned to 26f38c119c)
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.
Example fix
// before: host code sets a fixed priority before starting ty pthread_setschedparam(thread, SCHED_FIFO, ¶m); ty_server::start(...); // after: start ty on an untouched thread, then customize elsewhere ty_server::start(...);
Defensive patterns
Strategy: try-catch
Validate before calling
// macOS: ensure the host thread has not opted out of QoS before hosting ty
let is_qos_compatible = std::env::var("CARGO_CFG_TARGET_OS").as_deref() != Ok("macos")
|| !manual_scheduling_used;
if !is_qos_compatible { /* run ty on a fresh default-priority thread */ } Try / catch
// The API panics, so guard by construction; catch at the thread boundary:
std::panic::catch_unwind(|| ty_server::run_on_current_thread())
.map_err(|_| "thread opted out of QoS; re-run on a clean thread") Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- tried to get QoS of thread which has opted out of QoS
- InternalError
- Server notebook document could not be converted to ty's note
- `python_extension` is not expected to be combined with the i
- InternalError
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/90904f06b816b3d6.
Report an issue: GitHub.