astrid-runtime/astrid · error

named-pipe peer PID did not identify the opened process

Error message

named-pipe peer PID did not identify the opened process

What it means

peer_process_identity opens the peer PID with OpenProcess and then calls GetProcessId on the returned handle to confirm the handle really refers to that PID. If the handle resolves to a different PID (handle recycling / PID reuse or an API inconsistency), identity cannot be trusted and the library fails closed with PermissionDenied.

Source

Thrown at crates/astrid-core/src/local_transport/windows.rs:437

        if peer_process_id(stream)? != self.process_id {
            return Err(io::Error::new(
                io::ErrorKind::PermissionDenied,
                "named-pipe peer process changed during authentication",
            ));
        }
        Ok(())
    }
}

fn peer_process_identity(stream: &LocalStream) -> io::Result<VerifiedPeerProcess> {
    let process_id = peer_process_id(stream)?;
    let process = unsafe { OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, process_id) };
    if process.is_null() {
        return Err(last_error("failed to open named-pipe peer process"));
    }
    let process = OwnedHandle(process);
    if unsafe { GetProcessId(process.0) } != process_id {
        return Err(io::Error::new(
            io::ErrorKind::PermissionDenied,
            "named-pipe peer PID did not identify the opened process",
        ));
    }

    let mut token = ptr::null_mut();
    let opened = unsafe { OpenProcessToken(process.0, TOKEN_QUERY, &raw mut token) };
    if opened == 0 || token.is_null() {
        return Err(last_error("failed to open named-pipe peer process token"));
    }
    let user_sid = token_user_sid(&OwnedHandle(token))?;
    Ok(VerifiedPeerProcess {
        process_id,
        user_sid,
        _process: process,
    })
}

View on GitHub (pinned to affd8760f4)

Solutions

  1. Treat the peer as unverified: re-authenticate the connection (new handshake, new PID capture).
  2. Retry the connection promptly — PID reuse windows are usually transient.
  3. If this recurs, verify the client is not dying mid-handshake and that only one process is connecting per pipe instance.
Defensive patterns

Strategy: retry

Try / catch

match result {
    Err(e) if e.to_string().contains("did not identify the opened process") => {
        // transient PID/handle inconsistency: re-authenticate with backoff
        retry_with_backoff(authenticate, 3)
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling connect/accept (via peer_is_current_user or require_current_user_process_peer) when the PID captured from the pipe was recycled by the OS between capture and OpenProcess, or OpenProcess returned a mismatched handle.

Common situations: Long-lived servers re-verifying peers whose PIDs were reused after process churn; heavily loaded systems with rapid process creation/destruction.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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