rust-lang/rust-analyzer · error
tried to set QoS of thread which has opted out of QoS
Error message
tried to set QoS of thread which has opted out of QoS (os error {errno}) What it means
On macOS, rust-analyzer manages thread priority exclusively through QoS (Quality of Service) APIs (`pthread_set_qos_class_self_np`). If setting the QoS class returns ENOTSUP/ENOTSCHED (errno stored), the thread has previously opted out of the QoS system — e.g. via `pthread_setschedparam`-style scheduling calls incompatible with QoS — and can no longer use QoS APIs. The code deliberately panics instead of returning an error to uphold the invariant that only QoS APIs are used for thread intent.
Solutions
- Stop using non-QoS scheduling APIs (`pthread_setschedparam` etc.) on threads managed by stdx::thread; rely on ThreadIntent/QoS only
- Spawn a fresh thread that has never had its policy modified and use QoS intent APIs from the start
- If you must use manual scheduling, do not attempt QoS calls afterward on that thread
Example fix
// before pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m); stdx::thread::set_current_thread_qos_class(...).unwrap(); // panics // after // drop the manual scheduling call entirely stdx::thread::set_current_thread_qos_class(...).unwrap();
Defensive patterns
Strategy: validation
Validate before calling
// Before managing intent, confirm the thread hasn't been policy-modified:
let class = libc::qos_class_self(); // probing is safe
if class == libc::QOS_CLASS_UNSPECIFIED {
eprintln!("thread opted out of QoS; skip set_current_thread_qos_class");
} else {
stdx::thread::set_current_thread_qos_class(intent)?;
} Try / catch
// Guard the process-level invariant during embedding:
let result = std::panic::catch_unwind(||
stdx::thread::set_current_thread_qos_class(ThreadIntent::Worker)
); Prevention
- Never call pthread_setschedparam/thread_policy_set on stdx::thread-managed threads
- Use ThreadIntent/QoS as the only priority mechanism on macOS
- If manual scheduling is required, run it on separate threads from intent-managed ones
When it happens
Trigger: Calling `set_current_thread_qos_class` on a thread whose scheduling was previously modified by a non-QoS API such as `pthread_setschedparam`, `thread_policy_set`, or manual scheduling; mixing `stdx::thread` intent APIs with platform-specific priority tweaks in the same thread.
Common situations: Developers integrating custom thread priority/scheduling code (real-time audio-style policies) alongside rust-analyzer's thread pool on macOS; embedding rust-analyzer in an app that adjusts thread policies on its worker threads.
Related errors
- tried to get QoS of thread which has opted out of QoS
- an edit target must still be present
- AstIdMap node mismatch with node
- bad kind
- bad spacing
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/226964a51424f888.
Report an issue: GitHub.
Appendix: source
Thrown at crates/stdx/src/thread/intent.rs:198
};
let code = unsafe { libc::pthread_set_qos_class_self_np(c, 0) };
if code == 0 {
return;
}
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 e8f7e90aa3)