{"record":{"id":"8117fcfee01ddb82","repo":"abi/screenshot-to-code","slug":"no-available-port-found-from-start-port-to-star","errorCode":null,"errorMessage":"No available port found from {start_port} to {start_port + max_attempts - 1}","messagePattern":"No available port found from (.+?) to (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"backend/start.py","lineNumber":23,"sourceCode":"\n\ndef is_port_available(host: str, port: int) -> bool:\n    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        try:\n            sock.bind((host, port))\n        except OSError:\n            return False\n\n    return True\n\n\ndef find_available_port(host: str, start_port: int, max_attempts: int) -> int:\n    for port in range(start_port, start_port + max_attempts):\n        if is_port_available(host, port):\n            return port\n\n    raise RuntimeError(\n        f\"No available port found from {start_port} to \"\n        f\"{start_port + max_attempts - 1}\"\n    )\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"--host\", default=\"127.0.0.1\")\n    parser.add_argument(\"--port\", type=int, default=7001)\n    parser.add_argument(\"--max-port-attempts\", type=int, default=20)\n    args = parser.parse_args()\n\n    port = find_available_port(args.host, args.port, args.max_port_attempts)\n    if port != args.port:\n        print(f\"Port {args.port} is in use. Starting backend on port {port}.\")\n\n    uvicorn.run(\"main:app\", host=args.host, port=port, reload=True)\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/abi/screenshot-to-code/blob/d026163f586dfa8c5c10d28c36edd59a9d3b0e88/backend/start.py#L5-L41","documentation":"RuntimeError(\"No available port found from {start} to {end}\") raised by find_available_port() in backend/start.py when every port in the inclusive-at-start, exclusive-at-end range fails is_port_available()'s bind() test. start.py uses this to pick a uvicorn port (default 7001, 20 attempts => 7001-7020), so the failure means the backend cannot start at all. bind() fails on OSError, covering ports already bound, ports in exclusive use, and addresses/interfaces that cannot be bound on the chosen --host.","triggerScenarios":"Starting the backend with defaults while 20 prior dev-server instances (or other apps) hold 7001-7020; passing --host of an interface that is down or not owned by the process; running under an environment where loopback binding is restricted.","commonSituations":"Repeated `uvicorn main:app --reload` sessions that never got killed; Docker port mappings consuming the range; another service (e.g. airtower/ADS-B on 7001-adjacent ports or a previously orphaned start.py) squatting the range.","solutions":["Find and kill the squatters: ss -ltnp 'sport >= :7001' (or lsof -i :7001-7020), then kill the stale PIDs","Start on a different base port: python start.py --port 7100","Widen the scan: python start.py --max-port-attempts 100","If --host was set to a specific interface, verify it is up (ip addr) or fall back to the default 127.0.0.1"],"exampleFix":"# before\npython start.py  # RuntimeError: No available port found from 7001 to 7020\n\n# after\npython start.py --port 7100  # or first: kill $(lsof -t -i :7001-7020)","handlingStrategy":"fallback","validationCode":"import socket\n\ndef ports_free(host: str, start: int, count: int) -> list[int]:\n    free = []\n    for port in range(start, start + count):\n        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:\n            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n            try:\n                s.bind((host, port)); free.append(port)\n            except OSError:\n                pass\n    return free  # empty list => start.py will raise RuntimeError","typeGuard":null,"tryCatchPattern":"try:\n    port = find_available_port(host, start_port, max_attempts)\nexcept RuntimeError:\n    port = 7100  # fallback: fixed alternate port, or kill stale servers first (lsof -t -i :7001-7020 | xargs kill)","preventionTips":["Kill stale uvicorn/start.py instances before starting a new dev session","Pass --port explicitly in shared or containerized environments rather than relying on the scan","Map only the ports you need in Docker; avoid publishing wide port ranges that squat 7001-7020"],"tags":["port-binding","networking","startup","uvicorn","dev-server"],"backgroundTag":null,"analyzedSha":"d026163f586dfa8c5c10d28c36edd59a9d3b0e88","analyzedAt":"2026-08-14T22:02:06.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}