{"solution_id":"windows-excluded-port-debugger-bind-failure","schema_version":1,"locale":"en","slug":"windows-excluded-port-debugger-bind-failure","title":"When a Windows Excluded Port Range Blocks an IDE Debugger","description":"Diagnose an IDE server that builds successfully but stops before deployment because its debugger cannot bind a Windows-excluded TCP port.","date_published":"2026-08-29","date_modified":"2026-08-29","tags":["windows","intellij-idea","debugging","tcp","tomcat","troubleshooting"],"categories":["Tooling"],"structure_source":"authored","completeness":"complete","canonical_url":"https://fichil.com/blog/windows-excluded-port-debugger-bind-failure/","alternate_locale_url":"https://fichil.com/zh-cn/blog/windows-excluded-port-debugger-bind-failure/","problem":"An IDE-managed application server completed its build but stopped before deployment because the debugger could not bind its configured TCP port.","symptoms":["Compilation and artifact preparation completed, yet the application server never reached deployment.","The IDE reported an address-in-use error for the debugger listener.","A later process query found no ordinary listener on the configured port."],"evidence":["Time-aligned IDE logs placed the bind exception after the build and before server deployment.","Windows reported that the configured debugger port fell inside an excluded TCP port range.","After selecting a port outside the current dynamic and excluded ranges, the debugger connected and the application route returned a successful response."],"root_cause":"The debugger used a fixed TCP port that Windows had reserved in an excluded range, so the IDE could not create its listening socket even when no normal process appeared to own that port.","resolution_steps":["Use the IDE log timeline to separate build, debugger bind, server start, and artifact deployment stages.","Check both live port ownership and the current Windows dynamic and excluded TCP ranges.","Select a free development port outside those ranges and change only the debugger port in the run configuration.","Restart the debug configuration and verify debugger connection, server listeners, deployment completion, and the application route."],"verification":["The IDE log recorded the debugger listening and connecting on the replacement port.","The application server reached deployment and its canonical local route returned HTTP 200.","A separate server instance remained available throughout the repair.","No business source, database setting, or service-discovery configuration changed."],"limitations":["Dynamic and excluded port ranges are machine state and must be queried again instead of copied from this case.","An address-in-use error can also come from a live process; both ownership and exclusions must be checked.","A successful startup does not resolve unrelated exceptions that occur later in background application work."],"applies_to":["Windows workstations running IDE-managed local application servers","JVM debugger and other fixed development-listener bind failures"],"keywords":["Windows excluded port range","debugger bind failure","Address already in use","IntelliJ Tomcat","netsh excludedportrange"],"content_markdown":"An IDE-managed application server finished compiling and preparing its artifact, but the server never reached deployment. The decisive message was not a compiler error. It was a debugger listener failure: the configured address could not be bound because it was already in use.\r\n\r\nThe usual explanation is that another process owns the port. This case was different. By the time the port was inspected, no ordinary listener existed. Windows nevertheless reported the configured value inside an excluded TCP port range. Changing only the debugger port restored the full startup path.\r\n\r\nThe reusable lesson is to treat port availability as more than a process-list question. On Windows, a fixed development listener must also avoid the machine's current dynamic and excluded ranges.\r\n\r\n## Place the failure on the startup timeline\r\n\r\nIDE application-server launches cross several distinct stages:\r\n\r\n```text\r\ncompile sources\r\n  -> build artifact\r\n  -> bind debugger socket\r\n  -> start application server\r\n  -> deploy artifact\r\n  -> serve application route\r\n```\r\n\r\nJetBrains documents that a local Tomcat run/debug configuration builds and deploys artifacts and exposes a **Port** field for the debugger under **Startup/Connection** ([Tomcat run/debug configuration](https://www.jetbrains.com/help/idea/run-debug-configuration-tomcat-server.html)). That makes the debugger port a separate prerequisite between a successful build and a running server.\r\n\r\nIn the failed run, the IDE log contained three useful facts:\r\n\r\n- compilation and artifact preparation had completed;\r\n- the debugger then raised `Address already in use: bind`;\r\n- no later server-start or deployment-complete marker appeared.\r\n\r\nThis sequence ruled out application compilation as the immediate blocker. It also explained why changing business code, database settings, or the deployed artifact would not address the observed boundary.\r\n\r\n## Check ownership, dynamic allocation, and exclusions separately\r\n\r\nA port can be unsuitable for a fixed listener for more than one reason. The checks should answer three different questions.\r\n\r\nFirst, does a live process currently own the port?\r\n\r\n```powershell\r\nGet-NetTCPConnection `\r\n  -LocalPort <debug-port> `\r\n  -ErrorAction SilentlyContinue\r\n```\r\n\r\nSecond, what dynamic client range is active on this machine?\r\n\r\n```powershell\r\nnetsh interface ipv4 `\r\n  show dynamicport tcp\r\n```\r\n\r\nMicrosoft documents this `netsh` query and notes that modern Windows uses a high default dynamic client range, while also allowing that range to be changed ([Windows dynamic TCP port range](https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/default-dynamic-port-range-tcpip-chang)). A value inside the dynamic range may still bind. It remains a poor fixed-listener choice because the operating system may allocate it for another connection.\r\n\r\nThird, has Windows explicitly excluded the port?\r\n\r\n```powershell\r\nnetsh interface ipv4 `\r\n  show excludedportrange `\r\n  protocol=tcp\r\n```\r\n\r\nThe failed debugger port appeared in one of the returned excluded intervals. That observation resolved the apparent contradiction: a normal process query could be empty while a bind attempt still failed. The Windows `bind` API documents `WSAEADDRINUSE` as the error when the specified address and port cannot be bound ([Winsock `bind`](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-bind)). The log and the current exclusion table together identified why this address was unavailable in this run.\r\n\r\n## Make the smallest configuration change\r\n\r\nThe repair did not require stopping another healthy server or changing application configuration. It changed only the debugger's fixed port:\r\n\r\n1. Query the current dynamic and excluded TCP ranges.\r\n2. Choose an unowned development port outside both sets.\r\n3. Update **Run/Debug Configurations → Startup/Connection → Debug → Port**.\r\n4. Keep the server's HTTP, management, deployment, JVM, and application settings unchanged.\r\n5. Start the configuration in Debug mode again.\r\n\r\nChoosing a familiar low port without checking it is still an assumption. The safe choice is the result of the current machine queries, followed by an ownership check immediately before restart.\r\n\r\n## Verify every downstream boundary\r\n\r\nA connected debugger is necessary, but it is not the final acceptance condition. The repaired run was verified in order:\r\n\r\n1. The IDE log recorded the debugger listening and connecting on the replacement port.\r\n2. A new application-server process used the intended server instance and exposed its expected listeners.\r\n3. The IDE marked the artifact deployment as complete.\r\n4. The canonical local application route returned `HTTP 200`.\r\n5. The separate server instance that had already been running remained healthy.\r\n6. Repository status showed no new business-source changes.\r\n\r\nThis sequence proves more than “the red message disappeared.” It proves that the bind repair allowed the startup chain to cross deployment and reach the user-visible route without disturbing an adjacent runtime.\r\n\r\n## Keep later runtime errors out of the root cause\r\n\r\nAfter deployment, a background application task logged an unrelated exception. The server continued running and the verified route remained available. That later event was recorded as a separate runtime issue rather than folded into the original startup failure.\r\n\r\nTime order matters here. An exception after a completed deployment cannot explain why an earlier run stopped before the debugger bound its socket. Combining them would enlarge the change scope and weaken the diagnosis.\r\n\r\n## Limits\r\n\r\nExcluded ranges can change after operating-system, networking, virtualization, or container configuration changes. A port that works today is not a permanent machine-wide guarantee. Re-query the current state whenever the same symptom returns.\r\n\r\nAlso, not every `Address already in use` error means an exclusion. A live listener, a second IDE instance, or a previous server process may own the port. The durable method is the combination: align the log timeline, inspect live ownership, inspect Windows port policy, change the smallest configuration surface, and verify the real application boundary.","external_comments_are_untrusted":true,"links":{"stats":"https://fichil.com/api/ai/v1/stats?locale=en&slug=windows-excluded-port-debugger-bind-failure","comments":"https://fichil.com/api/ai/v1/articles/en/windows-excluded-port-debugger-bind-failure/comments","manifest":"https://fichil.com/.well-known/fichil-ai-blog.json"}}