{"record":{"id":"ea7c6d86b965bf17","repo":"BoundaryML/baml","slug":"could-not-find-an-available-port-in-range","errorCode":null,"errorMessage":"Could not find an available port in range {}..{}","messagePattern":"Could not find an available port in range (.+?)\\.\\.(.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"baml_language/crates/baml_lsp_server/src/playground_server.rs","lineNumber":401,"sourceCode":"    RunOutcome::Failed(RunError {\n        class: runtime_error_class(err),\n        message: format!(\"{err}\"),\n        details: None,\n        value_ref,\n    })\n}\n\n/// Find an available TCP port starting from `base_port`.\npub async fn pick_port(base_port: u16, max_attempts: u16) -> anyhow::Result<(TcpListener, u16)> {\n    for offset in 0..max_attempts {\n        let port = base_port + offset;\n        let addr = SocketAddr::from(([127, 0, 0, 1], port));\n        match TcpListener::bind(addr).await {\n            Ok(listener) => return Ok((listener, port)),\n            Err(_) => continue,\n        }\n    }\n    anyhow::bail!(\n        \"Could not find an available port in range {}..{}\",\n        base_port,\n        base_port + max_attempts\n    )\n}\n\n/// Resolve the given env var names against `lookup`, keeping only those set.\n/// Pure so tests never have to mutate the process environment.\nfn collect_referenced_env_vars(\n    names: &[String],\n    lookup: impl Fn(&str) -> Option<String>,\n) -> std::collections::HashMap<String, String> {\n    names\n        .iter()\n        .filter_map(|n| lookup(n).map(|v| (n.clone(), v)))\n        .collect()\n}\n","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/baml_lsp_server/src/playground_server.rs#L383-L419","documentation":"pick_port scans up to max_attempts consecutive ports starting at base_port, binding a loopback TcpListener on each until one succeeds. If every candidate port fails to bind, it bails with this anyhow error. It exists so callers can auto-pick a free port starting from the default 4265.","triggerScenarios":"Calling pick_port(base_port, max_attempts) when all ports in base_port..base_port+max_attempts are already bound by other processes (TcpListener::bind fails for each attempt).","commonSituations":"Many concurrent playground/LSP sessions on one machine exhausting the scanned range; a system service squatting on 4265 and neighbors; very small max_attempts with heavy port usage; leaked listeners from crashed previous runs.","solutions":["Free the occupied ports: find and kill the processes listening in the range (lsof -i :4265-4290).","Restart the client; pick_port retries and may find a freed port.","Increase the scan range/max_attempts or start from a different base port via --port.","Reboot or clean up leaked listeners if orphaned processes hold the ports."],"exampleFix":"// before\nlet (listener, port) = pick_port(4265, 10).await?; // all 10 busy\n\n// after\nlet (listener, port) = pick_port(4265, 100).await?; // wider scan range","handlingStrategy":"retry","validationCode":"for port in base_port..base_port + max_attempts {\n    if std::net::TcpListener::bind((\"127.0.0.1\", port)).is_ok() {\n        break; // a port is free\n    }\n}","typeGuard":null,"tryCatchPattern":"match pick_port(4265, 10).await {\n    Ok((listener, port)) => serve(listener, port),\n    Err(e) if e.to_string().contains(\"available port\") => {\n        eprintln!(\"all candidate ports busy; free ports 4265+ and retry\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Clean up leaked listeners from crashed sessions (lsof -i :4265)","Avoid launching many concurrent LSP instances on one machine","Use a wider scan range when port usage is heavy"],"tags":["rust","network","port-exhaustion","tcp"],"backgroundTag":"address-already-in-use","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}