{"record":{"id":"72fe10f33f994b11","repo":"BloopAI/vibe-kanban","slug":"client-server-address-already-set","errorCode":null,"errorMessage":"client server address already set","messagePattern":"client server address already set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/server/src/main.rs","lineNumber":136,"sourceCode":"    let actual_main_port = main_listener.local_addr()?.port();\n\n    let proxy_listener = tokio::net::TcpListener::bind(format!(\"{host}:{proxy_port}\")).await?;\n    let actual_proxy_port = proxy_listener.local_addr()?.port();\n\n    if let Err(e) = write_port_file_with_proxy(actual_main_port, Some(actual_proxy_port)).await {\n        tracing::warn!(\"Failed to write port file: {}\", e);\n    }\n\n    tracing::info!(\n        \"Main server on :{}, Preview proxy on :{}\",\n        actual_main_port,\n        actual_proxy_port\n    );\n\n    deployment\n        .client_info()\n        .set_server_addr(main_listener.local_addr()?)\n        .expect(\"client server address already set\");\n    deployment\n        .client_info()\n        .set_preview_proxy_port(actual_proxy_port)\n        .expect(\"client preview proxy port already set\");\n\n    let app_router = routes::router(deployment.clone());\n\n    // Production only: open browser\n    if !cfg!(debug_assertions) {\n        tracing::info!(\"Opening browser...\");\n        let browser_port = actual_main_port;\n        tokio::spawn(async move {\n            if let Err(e) =\n                utils::browser::open_browser(&format!(\"http://127.0.0.1:{browser_port}\")).await\n            {\n                tracing::warn!(\n                    \"Failed to open browser automatically: {}. Please open http://127.0.0.1:{} manually.\",\n                    e,","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/crates/server/src/main.rs#L118-L154","documentation":"set_server_addr stores the listener's local address in a once-only (OnceCell-style) field of client_info. The .expect(\"client server address already set\") panics if the address was already initialized earlier in the process. It is an internal invariant check: server_addr must be set exactly once during startup.","triggerScenarios":"DeploymentImpl::new (or another startup path) already called client_info().set_server_addr() before line 136, so the second call finds the cell occupied and panics. Only reachable if startup code is duplicated or reordered.","commonSituations":"Modifying main.rs so initialization runs twice (re-created deployment, retried listener setup); merging code that sets the address in both a fallback and main path; refactoring that moved DeploymentImpl::new after address configuration.","solutions":["Verify set_server_addr is called exactly once in the startup path; remove duplicate calls.","If the address may legitimately change, replace once-only semantics with set/replace (RwLock/Mutex) or .ok() instead of expect.","Check that no retry/test wrapper re-runs the initialization block within the same process."],"exampleFix":"// before\ndeployment.client_info().set_server_addr(main_listener.local_addr()?)\n    .expect(\"client server address already set\");\n// after\ndeployment.client_info()\n    .set_server_addr(main_listener.local_addr()?)\n    .unwrap_or_else(|_| tracing::warn!(\"server addr already set; keeping existing value\"));","handlingStrategy":"validation","validationCode":"if deployment.client_info().server_addr().is_none() {\n    deployment.client_info()\n        .set_server_addr(main_listener.local_addr()?)?;\n}","typeGuard":null,"tryCatchPattern":"deployment.client_info()\n    .set_server_addr(main_listener.local_addr()?)\n    .unwrap_or_else(|_| tracing::debug!(\"server addr already configured\"));","preventionTips":["Call one-time initializers exactly once, from a single init function.","Search the codebase for duplicate set_server_addr call sites before refactoring startup.","Use .set().ok() or logged fallbacks instead of expect for idempotent-style setters.","Add a unit test that runs the full startup path once to catch double-init regressions."],"tags":["startup","initialization","invariant","panic"],"backgroundTag":"already-initialized-once-cell","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}