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

  1. 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}.
  2. 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.
  3. Retry transient OS failures (out-of-memory, transient handle errors) with backoff.
  4. 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

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


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/f3ac6eba352f25f8. Report an issue: GitHub.