{"record":{"id":"0fc4c9c1cfe11b18","repo":"zed-industries/zed","slug":"cannot-have-two-different-ports-in-debug-configura","errorCode":null,"errorMessage":"Cannot have two different ports in debug configuration","messagePattern":"Cannot have two different ports in debug configuration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dap_adapters/src/python.rs","lineNumber":379,"sourceCode":"            .unwrap_or_else(|| {\n                (\n                    config\n                        .config\n                        .get(\"port\")\n                        .and_then(|port| port.as_u64().map(|p| p as u16)),\n                    config.config.get(\"host\").and_then(|host| host.as_str()),\n                )\n            });\n\n        let is_attach_with_connect = if config\n            .config\n            .get(\"request\")\n            .is_some_and(|val| val.as_str().is_some_and(|request| request == \"attach\"))\n        {\n            if tcp_connection.host.is_some() && config_host.is_some() {\n                bail!(\"Cannot have two different hosts in debug configuration\")\n            } else if tcp_connection.port.is_some() && config_port.is_some() {\n                bail!(\"Cannot have two different ports in debug configuration\")\n            }\n\n            if let Some(hostname) = config_host {\n                tcp_connection.host = Some(hostname.parse().context(\"invalid IP address\")?);\n            }\n            tcp_connection.port = config_port;\n            DebugpyLaunchMode::AttachWithConnect { host: config_host }\n        } else {\n            DebugpyLaunchMode::Normal\n        };\n\n        let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;\n\n        let python_path = if let Some(toolchain) = python_from_toolchain {\n            Some(toolchain)\n        } else {\n            Self::system_python_name(delegate).await\n        };","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/dap_adapters/src/python.rs#L361-L397","documentation":"debugpy attach validation, port variant: on an attach request, if `tcp_connection.port` is already set and the adapter `config` object also carries a `\"port\"` key, Zed refuses to choose between two different port sources and bails (python.rs:379). It prevents connecting to the wrong debugpy listener.","triggerScenarios":"A Zed Python debug task where `tcp_connection: { \"port\": 5678 }` and `config: { \"port\": 9000 }` are both present with `request: \"attach\"`; also hit when a copied VS Code config keeps its port and the Zed-side port is added afterwards.","commonSituations":"Migrating launch.json snippets into Zed debug configs; changing the debugpy --listen port on one side but not the other; templates that pre-fill both fields.","solutions":["Keep the port in exactly one place — delete `\"port\"` from `config` and leave `tcp_connection.port` (or the reverse).","Make sure the surviving port matches the port debugpy actually listens on (`python -m debugpy --listen <port>`)."],"exampleFix":"// before\n{\n  \"adapter\": \"Python\",\n  \"request\": \"attach\",\n  \"tcp_connection\": { \"port\": 5678 },\n  \"config\": { \"port\": 9000 }\n}\n\n// after\n{\n  \"adapter\": \"Python\",\n  \"request\": \"attach\",\n  \"tcp_connection\": { \"host\": \"127.0.0.1\", \"port\": 5678 }\n}","handlingStrategy":"validation","validationCode":"// reject attach configs that define port in two places, before starting a session\nlet has_tcp_port = task.tcp_connection.as_ref().is_some_and(|t| t.port.is_some());\nlet has_config_port = task.config.get(\"request\") == Some(\"attach\") && task.config.get(\"port\").is_some();\nif has_tcp_port && has_config_port {\n    return Err(anyhow!(\"remove `port` from either tcp_connection or config\"));\n}","typeGuard":"fn defines_port_once(tcp: &Option<TcpConnection>, config: &serde_json::Value) -> bool {\n    let in_tcp = tcp.as_ref().is_some_and(|t| t.port.is_some());\n    let in_config = config.get(\"port\").is_some_and(|v| !v.is_null());\n    !(in_tcp && in_config)\n}","tryCatchPattern":"Catch at config-load time and surface both port values in the message so the mismatch is obvious; do not attempt a default choice.","preventionTips":["Keep the port only in tcp_connection and make it match the debugpy --listen port.","Parameterize one variable (e.g. 5678) and reference it in both places if configs are generated.","Lint for duplicate transport keys when configs are committed."],"tags":["debugger","debugpy","configuration","attach","zed"],"backgroundTag":"conflicting-config-values","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}