diem/diem · error · io::Error

MemoryListener unknown error

Error message

MemoryListener unknown error

What it means

MemoryListener (the in-memory socket listener used by memsocket for tests/simulations) is backed by a stream of incoming connections. When that stream is closed and returns None — i.e. the listener was dropped or the socket registry shut down — poll_accept converts the termination into an io::Error with this message, since std's Listener API has no graceful 'closed' signal.

Source

Thrown at network/memsocket/src/lib.rs:187

    /// while let Some(stream) = incoming.next().await {
    ///     match stream {
    ///         Ok(stream) => {
    ///             println!("new connection!");
    ///         },
    ///         Err(e) => { /* connection failed */ }
    ///     }
    /// }
    /// # Ok(())}
    /// ```
    pub fn incoming(&mut self) -> Incoming<'_> {
        Incoming { inner: self }
    }

    fn poll_accept(&mut self, context: &mut Context) -> Poll<Result<MemorySocket>> {
        match Pin::new(&mut self.incoming).poll_next(context) {
            Poll::Ready(Some(socket)) => Poll::Ready(Ok(socket)),
            Poll::Ready(None) => {
                let err = Error::new(ErrorKind::Other, "MemoryListener unknown error");
                Poll::Ready(Err(err))
            }
            Poll::Pending => Poll::Pending,
        }
    }
}

/// Stream returned by the `MemoryListener::incoming` function representing the
/// stream of sockets received from a listener.
#[must_use = "streams do nothing unless polled"]
#[derive(Debug)]
pub struct Incoming<'a> {
    inner: &'a mut MemoryListener,
}

impl<'a> Stream for Incoming<'a> {
    type Item = Result<MemorySocket>;

View on GitHub (pinned to fc4714a8ea)

Solutions

  1. Ensure the accept loop is stopped/dropped before the MemoryListener or registry is torn down
  2. Hold a clone of the listener/registry for the lifetime of the accept task
  3. Treat this error as 'listener closed' and exit the accept loop instead of retrying
  4. If seen in tests, fix shutdown ordering (abort server tasks before dropping sockets)

Example fix

// before
loop { let conn = listener.accept().await?; spawn(handle(conn)); }
// after
loop {
    match listener.accept().await {
        Ok(conn) => spawn(handle(conn)),
        Err(e) if e.kind() == ErrorKind::Other && e.to_string().contains("MemoryListener unknown error") => break, // listener closed
        Err(e) => return Err(e.into()),
    }
}
Defensive patterns

Strategy: try-catch

Try / catch

// treat the error as listener-closed and stop accepting
match listener.accept().await {
    Ok(socket) => /* handle */ ,
    Err(e) if e.to_string().contains("MemoryListener unknown error") => break,
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling accept() on a MemoryListener whose underlying incoming stream has ended: the MemorySocket listener was dropped, the shared incoming channel was closed, or the memsocket registry shut down while a task was still accepting.

Common situations: Async test harness drops the socket registry or listener while a server task is still polling accept; simulation code that closes listeners without first stopping accept loops; shutdown-ordering races in tests using network builders built on memsocket.

Related errors


AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04). Data as JSON: /api/errors/1cfd3178b7ef7d36. Report an issue: GitHub.