rust-lang/rust-analyzer · error
tried to get QoS of thread which has opted out of QoS
Error message
tried to get QoS of thread which has opted out of QoS
What it means
The macOS counterpart of reading thread priority: `get_current_thread_qos_class` panics when the thread reports the 'unspecified' QoS class, which happens once a thread has opted out of QoS via manual scheduling APIs (e.g. `pthread_setschedparam`) or manual scheduling modes. As with the setter, the code panics rather than returning an error to preserve the invariant that only QoS APIs manage thread intent.
Source
Thrown at crates/stdx/src/thread/intent.rs:254
let errno = unsafe { *libc::__error() };
unreachable!("`pthread_get_qos_class_np` failed unexpectedly (os error {errno})");
}
match qos_class_raw {
libc::qos_class_t::QOS_CLASS_USER_INTERACTIVE => Some(QoSClass::UserInteractive),
libc::qos_class_t::QOS_CLASS_USER_INITIATED => Some(QoSClass::UserInitiated),
libc::qos_class_t::QOS_CLASS_DEFAULT => None, // QoS has never been set
libc::qos_class_t::QOS_CLASS_UTILITY => Some(QoSClass::Utility),
libc::qos_class_t::QOS_CLASS_BACKGROUND => Some(QoSClass::Background),
libc::qos_class_t::QOS_CLASS_UNSPECIFIED => {
// Using manual scheduling APIs causes threads to “opt out” of QoS.
// At this point they become incompatible with QoS,
// and as such have the “unspecified” QoS class.
//
// Panic instead of returning an error
// to maintain the invariant that we only use QoS APIs.
panic!("tried to get QoS of thread which has opted out of QoS")
}
}
}
pub(super) fn thread_intent_to_qos_class(intent: ThreadIntent) -> QoSClass {
match intent {
ThreadIntent::Worker => QoSClass::Utility,
ThreadIntent::LatencySensitive => QoSClass::UserInitiated,
}
}
}
// FIXME: Windows has QoS APIs, we should use them!
#[cfg(not(target_vendor = "apple"))]
mod imp {
use super::ThreadIntent;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]View on GitHub (pinned to e8f7e90aa3)
Solutions
- Remove manual scheduling calls from threads whose intent is managed via ThreadIntent/QoS
- Run the intent/QoS logic on a freshly spawned, unmodified thread
- Treat QoS as the single source of truth for thread priority in the process
Defensive patterns
Strategy: validation
Validate before calling
// Detect QoS opt-out before reading intent:
let class = libc::qos_class_self();
if class == libc::QOS_CLASS_UNSPECIFIED {
// thread opted out; do not call get_current_thread_qos_class
} Try / catch
let qos = std::panic::catch_unwind(||
stdx::thread::get_current_thread_qos_class()
).unwrap_or(None); // treat as unknown priority Prevention
- Avoid mixing manual scheduling APIs with QoS reads on the same thread
- Check QOS_CLASS_UNSPECIFIED via raw APIs before invoking the helper
- Document thread-policy constraints for embedders of rust-analyzer
When it happens
Trigger: Calling `get_current_thread_qos_class` on a thread that previously used manual scheduling APIs, causing it to report QOS_CLASS_UNSPECIFIED; measuring/adjusting intent on a thread whose policy was changed by embedding code.
Common situations: Same family as the setter panic: mixing rust-analyzer's ThreadIntent abstraction with platform-specific thread priority controls on macOS; libraries that tweak thread policy when they attach to host threads.
Related errors
- tried to set QoS of thread which has opted out of QoS (os er
- We explicitly do not provide canonicalization API, as that i
- bad kind {other}
- bad spacing {other}
- bad tag: {other}
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/3e1d67386fb1d7b4.
Report an issue: GitHub.