python/cpython · warning · ValueError

Node can't be used without a value attribute.

Error message

Node can't be used without a value attribute.

What it means

Debug-mode guard in BaseSelectorEventLoop.sock_accept(): before scheduling an asynchronous accept, the loop requires the listening socket to be non-blocking. With debug mode on and a nonzero/None timeout on the socket, the call raises ValueError instead of risking a blocking accept() that would freeze the loop.

Source

Thrown at Lib/_ast_unparse.py:333

            self.write("await")
            if node.value:
                self.write(" ")
                self.set_precedence(_Precedence.ATOM, node.value)
                self.traverse(node.value)

    def visit_Yield(self, node):
        with self.require_parens(_Precedence.YIELD, node):
            self.write("yield")
            if node.value:
                self.write(" ")
                self.set_precedence(_Precedence.ATOM, node.value)
                self.traverse(node.value)

    def visit_YieldFrom(self, node):
        with self.require_parens(_Precedence.YIELD, node):
            self.write("yield from ")
            if not node.value:
                raise ValueError("Node can't be used without a value attribute.")
            self.set_precedence(_Precedence.ATOM, node.value)
            self.traverse(node.value)

    def visit_Raise(self, node):
        self.fill("raise")
        if not node.exc:
            if node.cause:
                raise ValueError(f"Node can't use cause without an exception.")
            return
        self.write(" ")
        self.traverse(node.exc)
        if node.cause:
            self.write(" from ")
            self.traverse(node.cause)

    def do_visit_try(self, node):
        self.fill("try", allow_semicolon=False)
        with self.block():

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Call listen_sock.setblocking(False) right after bind()/listen()
  2. Build the listener inside async startup (e.g. loop.run_until_complete(start())) where non-blocking is set consistently
  3. For accept timeouts, wrap with asyncio.wait_for rather than socket timeouts

Example fix

# before
srv = socket.socket(); srv.bind(addr); srv.listen()
await loop.sock_accept(srv)  # debug: ValueError
# after
srv = socket.socket(); srv.bind(addr); srv.listen()
srv.setblocking(False)
await loop.sock_accept(srv)
Defensive patterns

Strategy: validation

Validate before calling

srv = socket.socket()
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(addr)
srv.listen(128)
srv.setblocking(False)               # before loop use

conn, peer = await loop.sock_accept(srv)

Try / catch

try:
    await loop.sock_accept(srv)
except ValueError as e:
    if 'non-blocking' in str(e):
        srv.setblocking(False)
        return await loop.sock_accept(srv)
    raise

Prevention

When it happens

Trigger: await loop.sock_accept(listen_sock) with debug mode enabled while the listening socket was created blocking (default) or carries a timeout — a very common oversight since listening sockets are often created in plain sync startup code before the loop runs.

Common situations: Servers whose listen socket setup code predates the asyncio port and never calls setblocking(False); tests with debug enabled rejecting previously-working servers; wrappers that set a timeout on the listener to bound startup races.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/7a4043cf4180647b. Report an issue: GitHub.