denoland/deno · error

dev server with HMR did not start within 15s

Error message

{name} dev server with HMR did not start within 15s

What it means

The desktop dev flow spawns the framework's HMR dev server and waits up to 15 seconds for it to print a URL, parsing each stdout line. If no URL appears within the window — server slow to boot, crashed, or printing a URL in an unrecognized format — this timeout fires. The server's echoed startup output appears in the log above the error.

Solutions

  1. Run the dev server manually with the same command (visible in the echoed log lines) to see the real startup error
  2. Pre-install dependencies so the 15s window isn't spent resolving, and free the expected port
  3. Free up CPU/disk — slow cold starts are the most common cause
  4. If the server does print a URL but in a custom format, restore the default banner or report a parsing issue
Defensive patterns

Strategy: retry

Validate before calling

// Preflight: ensure the dev port is free and deps are installed
const port = 5173;
const conn = await Deno.connect({ port }).catch(() => null);
if (conn) {
  conn.close();
  throw new Error(`port ${port} already in use — stop the other dev server`);
}
try {
  await Deno.stat("node_modules");
} catch {
  throw new Error("dependencies not installed — run the install step first");
}

Try / catch

Catch the timeout, echo the captured startup log to identify the real cause (crash, slow boot, unrecognized URL format), fix that, then retry — don't just extend waiting blindly.

Prevention

When it happens

Trigger: Dev server takes more than 15s to first URL print (cold dependency install, huge project, slow disk), crashes on startup (port in use, invalid framework config), or its banner is customized so the URL line no longer matches Deno's parser.

Common situations: First run before dependencies are installed; port conflicts from an already-running dev server; resource-starved CI machines; frameworks with custom startup banners.

Related errors


AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20). Data as JSON: /api/errors/3e3edf41d4a64536. Report an issue: GitHub.

Appendix: source

Thrown at cli/tools/desktop.rs:1230

    deno_core::anyhow::anyhow!("failed to capture HMR dev server stdout")
  })?;
  let mut lines = BufReader::new(stdout).lines();

  let url = tokio::time::timeout(std::time::Duration::from_secs(15), async {
    while let Ok(Some(line)) = lines.next_line().await {
      let url = parse_dev_server_url(&line);
      // Echo the dev server's own startup output (banner, URL, warnings) so
      // it isn't swallowed while we scan for the URL.
      log::info!("{line}");
      if let Some(url) = url {
        return Ok(url);
      }
    }
    deno_core::anyhow::bail!("dev server exited without printing a URL")
  })
  .await
  .map_err(|_| {
    deno_core::anyhow::anyhow!(
      "{name} dev server with HMR did not start within 15s"
    )
  })??;

  // Keep forwarding the dev server's stdout so its HMR/compile logs stay
  // visible after startup instead of being silently swallowed. The task ends
  // on its own once the child is killed (on drop) and the pipe closes.
  tokio::spawn(async move {
    while let Ok(Some(line)) = lines.next_line().await {
      log::info!("{line}");
    }
  });

  Ok((url, child))
}

/// Launch the desktop app with HMR enabled after compilation.
///

View on GitHub (pinned to f7822238ca)