denoland/deno · error

invalid vsock addr

Error message

invalid vsock addr

What it means

cli/lib.rs:1257 validates the unstable DENO_UNSTABLE_CONTROL_SOCK environment variable when Deno boots under an external supervisor. For the "vsock" transport it requires the address to be <cid>:<port>; addr.split_once(':') returning None means the value after "vsock:" contains no colon at all (e.g. "vsock:2"), so Deno bails with "invalid vsock addr".

Source

Thrown at cli/lib.rs:1257

      Box<dyn AsyncRead + Unpin>,
      Box<dyn AsyncWrite + Send + Unpin>,
    ) = match addr.split_once(':') {
      Some(("unix", path)) => {
        let socket = UnixSocket::new_stream()?;
        socket.bind(path)?;
        let listener = socket.listen(1)?;
        let (stream, _) = listener.accept().await?;
        let (rx, tx) = stream.into_split();
        (Box::new(rx), Box::new(tx))
      }
      #[cfg(any(
        target_os = "android",
        target_os = "linux",
        target_os = "macos"
      ))]
      Some(("vsock", addr)) => {
        let Some((cid, port)) = addr.split_once(':') else {
          deno_core::anyhow::bail!("invalid vsock addr");
        };
        let cid = if cid == "-1" { u32::MAX } else { cid.parse()? };
        let port = port.parse()?;
        let addr = VsockAddr::new(cid, port);
        let listener = VsockListener::bind(addr)?;
        let (stream, _) = listener.accept().await?;
        let (rx, tx) = stream.into_split();
        (Box::new(rx), Box::new(tx))
      }
      _ => {
        deno_core::anyhow::bail!("invalid control sock");
      }
    };

    let mut buf = Vec::with_capacity(1024);
    BufReader::new(rx).read_until(b'\n', &mut buf).await?;

    tokio::spawn(async move {

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Set the full address: DENO_UNSTABLE_CONTROL_SOCK="vsock:<cid>:<port>" (e.g. vsock:2:5000); use cid -1 (VMADDR_CID_ANY) for the any address
  2. If you meant a local socket, use the unix transport instead: DENO_UNSTABLE_CONTROL_SOCK="unix:/path/to/sock"
  3. Fix the templating in your supervisor/cloud-init that produces the env value so the port is always present

Example fix

# before
DENO_UNSTABLE_CONTROL_SOCK=vsock:2 deno run -RNE --unstable-... main.ts

# after
DENO_UNSTABLE_CONTROL_SOCK=vsock:2:5000 deno run -RNE --unstable-... main.ts
Defensive patterns

Strategy: validation

Validate before calling

#!/bin/sh
# validate before exec'ing deno
VAL="$DENO_UNSTABLE_CONTROL_SOCK"
case "$VAL" in
  vsock:*) echo "$VAL" | grep -Eq '^vsock:-?[0-9]+:[0-9]+$' || { echo "bad vsock addr: $VAL"; exit 2; } ;;
esac
exec deno run main.ts

Prevention

When it happens

Trigger: Launching deno with DENO_UNSTABLE_CONTROL_SOCK=vsock:<cid>:<port> but omitting the port segment, e.g. DENO_UNSTABLE_CONTROL_SOCK="vsock:3"; also any vsock value where everything after the scheme is a bare token with no ':' separator.

Common situations: Firecracker/QEMU VM setups or cloud sandboxes that hand Deno a vsock control channel via env templating; supervisor config generation that drops the empty port; copying a unix-socket style value ("vsock:/run/sock") into a vsock stanza.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/89992c635ce7a5c0. Report an issue: GitHub.