vitejs/vite · error · Error

Cannot print server URLs before server is listening.

Error message

Cannot print server URLs before server is listening.

What it means

PreviewServer.printUrls reads server.resolvedUrls, which is populated only after the HTTP server is listening. Calling printUrls before listen resolves leaves resolvedUrls null and throws. It is a programmer error in sequencing the preview server lifecycle.

Solutions

  1. Await server.listen() before calling server.printUrls().
  2. Use the printUrls callback option of listen if available, so it runs exactly when listening completes.
  3. Guard the call: if (server.resolvedUrls) server.printUrls().
  4. Reorder your bootstrap so the listen promise settles first.

Example fix

// before
const server = await preview({})
server.printUrls()
await server.listen()
// after
const server = await preview({})
await server.listen()
server.printUrls()
Defensive patterns

Strategy: validation

Validate before calling

function safePrintUrls(server) {
  if (!server.resolvedUrls) throw new Error('Call server.printUrls() after server.listen() resolves')
  server.printUrls()
}

Type guard

function isListening(server): boolean {
  return server.resolvedUrls !== null
}

Prevention

When it happens

Trigger: Calling server.printUrls() synchronously right after createServer (preview) without awaiting server.listen(). Or calling it inside a callback that can fire before the listen promise resolves.

Common situations: Programmatic wrappers around Vite preview that rush printUrls, or refactors that reordered the listen/print order.

Related errors


AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11). Data as JSON: /api/errors/10c1a3323fb5f481. Report an issue: GitHub.

Appendix: source

Thrown at packages/vite/src/node/preview.ts:191

    server.resolvedUrls = null
  }

  const server: PreviewServer = {
    config,
    middlewares: app,
    httpServer,
    async close() {
      if (!closeServerPromise) {
        closeServerPromise = closeServer()
      }
      return closeServerPromise
    },
    resolvedUrls: null,
    printUrls() {
      if (server.resolvedUrls) {
        printServerUrls(server.resolvedUrls, options.host, logger.info)
      } else {
        throw new Error('Cannot print server URLs before server is listening.')
      }
    },
    bindCLIShortcuts(options) {
      bindCLIShortcuts(server as PreviewServer, options)
    },
  }

  const closeServerAndExit = async (_: unknown, exitCode?: number) => {
    try {
      await server.close()
    } finally {
      process.exitCode ??= exitCode ? 128 + exitCode : undefined
      process.exit()
    }
  }

  setupSIGTERMListener(closeServerAndExit)

View on GitHub (pinned to b4d66fee14)