BloopAI/vibe-kanban · error

client preview proxy port already set

Error message

client preview proxy port already set

What it means

set_preview_proxy_port stores the proxy port in a once-only field of client_info; the .expect("client preview proxy port already set") panics if the port was already set earlier in the process. Like the sibling set_server_addr call, this is a set-once invariant asserted during startup.

Source

Thrown at crates/server/src/main.rs:140

    if let Err(e) = write_port_file_with_proxy(actual_main_port, Some(actual_proxy_port)).await {
        tracing::warn!("Failed to write port file: {}", e);
    }

    tracing::info!(
        "Main server on :{}, Preview proxy on :{}",
        actual_main_port,
        actual_proxy_port
    );

    deployment
        .client_info()
        .set_server_addr(main_listener.local_addr()?)
        .expect("client server address already set");
    deployment
        .client_info()
        .set_preview_proxy_port(actual_proxy_port)
        .expect("client preview proxy port already set");

    let app_router = routes::router(deployment.clone());

    // Production only: open browser
    if !cfg!(debug_assertions) {
        tracing::info!("Opening browser...");
        let browser_port = actual_main_port;
        tokio::spawn(async move {
            if let Err(e) =
                utils::browser::open_browser(&format!("http://127.0.0.1:{browser_port}")).await
            {
                tracing::warn!(
                    "Failed to open browser automatically: {}. Please open http://127.0.0.1:{} manually.",
                    e,
                    browser_port
                );
            }
        });

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Audit the startup path so set_preview_proxy_port is invoked exactly once.
  2. If reconfiguration is expected, switch the field to a replaceable container (RwLock<Option<u16>>) instead of once-only semantics.
  3. Downgrade the expect to a logged no-op if overwriting is harmless in your deployment.

Example fix

// before
deployment.client_info().set_preview_proxy_port(actual_proxy_port)
    .expect("client preview proxy port already set");
// after
deployment.client_info().set_preview_proxy_port(actual_proxy_port)
    .unwrap_or_else(|_| tracing::warn!("preview proxy port already set; ignoring"));
Defensive patterns

Strategy: validation

Validate before calling

if deployment.client_info().preview_proxy_port().is_none() {
    deployment.client_info().set_preview_proxy_port(actual_proxy_port)?;
}

Try / catch

deployment.client_info()
    .set_preview_proxy_port(actual_proxy_port)
    .unwrap_or_else(|_| tracing::debug!("preview proxy port already configured"));

Prevention

When it happens

Trigger: The preview proxy port was already configured before line 140 — an earlier startup step, a retried init block, or duplicated code calling set_preview_proxy_port twice in one process.

Common situations: Refactoring startup so proxy setup runs in a retry loop; separate dev and prod code paths both configuring the proxy port; merging patches that each added the call; wrapping the init sequence in a function invoked more than once.

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/23c8fd081b278b39. Report an issue: GitHub.