denoland/deno · error · Error

ERR_SOCKET_ALREADY_BOUND

ERR_SOCKET_ALREADY_BOUND

Error message

Socket is already bound

What it means

Socket.bind() refuses to run unless the socket is in the BIND_STATE_UNBOUND state: binding again while a bind is in progress or after it completed throws ERR_SOCKET_ALREADY_BOUND. A dgram socket owns exactly one bind per lifetime; rebinding requires a new socket.

Source

Thrown at ext/node/polyfills/dgram.ts:413

   * server.bind(41234);
   * // Prints: server listening 0.0.0.0:41234
   * ```
   *
   * @param callback with no parameters. Called when binding is complete.
   */
  bind(port?: number, address?: string, callback?: () => void): this;
  bind(port: number, callback?: () => void): this;
  bind(callback: () => void): this;
  bind(options: BindOptions, callback?: () => void): this;
  bind(port_?: unknown, address_?: unknown /* callback */): this {
    let port = typeof port_ === "function" ? null : port_;

    healthCheck(this);

    const state = this[kStateSymbol];

    if (state.bindState !== BIND_STATE_UNBOUND) {
      throw new ERR_SOCKET_ALREADY_BOUND();
    }

    state.bindState = BIND_STATE_BINDING;

    const cb = arguments.length && arguments[arguments.length - 1];

    if (typeof cb === "function") {
      // deno-lint-ignore no-inner-declarations
      function removeListeners(this: Socket) {
        this.removeListener("error", removeListeners);
        this.removeListener("listening", onListening);
      }

      // deno-lint-ignore no-inner-declarations
      function onListening(this: Socket) {
        FunctionPrototypeCall(removeListeners, this);
        FunctionPrototypeCall(cb, this);
      }

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Bind once per Socket instance; create a new socket (createSocket('udp4')) to bind again
  2. Sequence startup with the 'listening' and 'error' events instead of re-calling bind
  3. In connect()-based flows, drop the manual bind and let connect auto-bind

Example fix

// before
sock.bind(port);
sock.bind(port); // retry on slow start — throws
// after
sock.bind(port);
sock.once("listening", () => console.log("bound"));
sock.once("error", (e) => { sock.close(); sock = dgram.createSocket("udp4"); sock.bind(port); });
Defensive patterns

Strategy: validation

Validate before calling

let bound = false;
function bindOnce(sock, ...args) {
  if (bound) return sock;
  bound = true;
  return sock.bind(...args);
}
sock.once("listening", () => { bound = true; });
sock.once("close", () => { bound = false; });

Try / catch

try { sock.bind(port); }
catch (e) {
  if (e.code === "ERR_SOCKET_ALREADY_BOUND") { /* already listening; continue */ }
  else throw e;
}

Prevention

When it happens

Trigger: s.bind(41234) called twice on the same socket; bind() racing with connect(), which auto-binds ({ port: 0, exclusive: true }) when the socket is unbound; retry logic that rebinds on error instead of closing and recreating the socket.

Common situations: Reconnect/retry loops that reuse the socket; startup code that binds in two places (e.g. init and an explicit start function); mixing manual bind with connect's implicit bind.

Related errors


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