astrid-runtime/astrid · error
{context}: {source}
Error message
{context}: {source} What it means
last_error is the helpers.rs wrapper that converts the last Win32 error (io::Error::last_os_error) into an io::Error whose message is '{context}: {source}'. It is the library's generic OS-call failure path for the Windows local transport (e.g. 'failed to read Windows token user', 'failed to create well-known Windows SID', 'failed to inspect named-pipe security descriptor control'). The original OS error code and kind are preserved, so the text after the colon is the authoritative Win32 failure.
Source
Thrown at crates/astrid-core/src/local_transport/windows/helpers.rs:13
//! Small Windows encoding and operating-system error helpers.
use std::ffi::OsStr;
use std::io;
use std::os::windows::ffi::OsStrExt as _;
pub(super) fn wide_nul(value: &OsStr) -> Vec<u16> {
value.encode_wide().chain(std::iter::once(0)).collect()
}
pub(super) fn last_error(context: &str) -> io::Error {
let source = io::Error::last_os_error();
io::Error::new(source.kind(), format!("{context}: {source}"))
}
View on GitHub (pinned to affd8760f4)
Solutions
- Read the {source} part of the message (e.g. 'Access is denied. (os error 5)') and map the Win32 code to the failing operation named in {context}.
- For 'Access is denied' on token reads, run the process under an account that can query its own token, or avoid restricted-token/AppContainer contexts.
- Retry transient OS failures (out-of-memory, transient handle errors) with backoff.
- If a specific context string recurs on a supported platform, report it — the wrapping helper should not normally fail.
Example fix
// before: ignoring the underlying OS code when logging
log::error!("transport setup failed: {}", err);
// after: surface both context and OS error for diagnosis
log::error!("transport setup failed: {err} (kind={:?})", err.kind());
// match err.raw_os_error() { Some(5) => /* access denied path */, ... } Defensive patterns
Strategy: try-catch
Validate before calling
// Preflight the operations that commonly fail before connecting:
// token readability (OpenProcessToken/GetTokenInformation) and CreateWellKnownSid succeed
let sid = current_user_sid().map_err(|e| format!("environment cannot query token: {e}"))?; Try / catch
match transport::connect(&path) {
Err(e) if e.raw_os_error() == Some(5) => eprintln!("access denied: {}", e), // inspect {context}: prefix
Err(e) if e.raw_os_error() == Some(8) => eprintln!("transient out-of-memory: {}", e), // retry
r => r?,
} Prevention
- Parse the '{context}: {source}' message — context names the failing Win32 call, source carries the os error code
- Run services under accounts that can query their own process token
- Retry on transient OS errors (memory/handle pressure) with backoff
- Log err.raw_os_error() alongside the message for support escalations
When it happens
Trigger: Any failing Win32 API call in the Windows local-transport path that reports via GetLastError — GetTokenInformation, CreateWellKnownSid, GetSecurityDescriptorControl, etc. — before pipe ACL validation even begins.
Common situations: Access denied when opening the process token under restricted service accounts; running in stripped-down environments (containers, minimal service sessions) where token/SID APIs fail; handle validity issues; Win32 ERROR_NOT_ENOUGH_MEMORY under resource pressure.
Related errors
- WinFsp daemon lease exceeds limit
- WinFsp service launch exceeds limit
- WinFsp service parent process is not alive
- WinFsp service parent start identity is invalid
- WinFsp stop timed out
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/f3ac6eba352f25f8.
Report an issue: GitHub.