{"record":{"id":"796e726505c7430e","repo":"NationalSecurityAgency/ghidra","slug":"address-must-be-port-or-host-port-796e72","errorCode":null,"errorMessage":"ADDRESS must be PORT or HOST:PORT","messagePattern":"ADDRESS must be PORT or HOST:PORT","errorType":"validation","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py","lineNumber":325,"sourceCode":"    to an ephemeral port on localhost. If only the port is given, it will\n    bind to that port on localhost. This command will block until the\n    connection is established.\n    \"\"\"\n\n    args = shlex.split(command)\n    host: str\n    port: Union[str, int]\n    if len(args) == 0:\n        host, port = '127.0.0.1', 0\n    elif len(args) == 1:\n        address = args[0]\n        parts = address.split(':')\n        if len(parts) == 1:\n            host, port = '127.0.0.1', parts[0]\n        elif len(parts) == 2:\n            host, port = parts\n        else:\n            raise RuntimeError(\"ADDRESS must be PORT or HOST:PORT\")\n    else:\n        raise RuntimeError(\"Usage: ghidra trace listen [ADDRESS]\")\n\n    STATE.require_no_client()\n    try:\n        s = socket.socket()\n        s.bind((host, int(port)))\n        host, port = s.getsockname()\n        s.listen(1)\n        print(f\"Listening at {host}:{port}...\")\n        c, (chost, cport) = s.accept()\n        s.close()\n        print(f\"Connection from {chost}:{cport}\")\n        STATE.client = Client(\n            c, util.LLDB_VERSION.display, methods.REGISTRY)\n    except ValueError:\n        raise RuntimeError(\"PORT must be numeric\")\n","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py#L307-L343","documentation":"`ghidra trace listen` accepts 0 or 1 address argument. With one argument it splits on `:`: exactly 1 part means port-only (host defaults to 127.0.0.1), exactly 2 means HOST:PORT, and anything else (3+ parts) raises this. So a raw IPv6 listen address triggers it.","triggerScenarios":"`ghidra trace listen ::1:8080`; `ghidra trace listen a:b:c`; any address token containing two or more colons.","commonSituations":"Trying to bind an IPv6 address directly; a mistyped address with extra colons.","solutions":["Use a plain PORT (`ghidra trace listen 8080`) or HOST:PORT (`ghidra trace listen 0.0.0.0:8080`)","Avoid raw IPv6 literals on this path; bind an IPv4 address or omit the host"],"exampleFix":"// before\nghidra trace listen ::1:8080\n// after\nghidra trace listen 127.0.0.1:8080","handlingStrategy":"validation","validationCode":"def valid_listen_addr(token: str) -> bool:\n    parts = token.split(':')\n    return len(parts) in (1, 2)","typeGuard":"from typing import Union, Tuple\ndef parse_listen_addr(token: str) -> Union[Tuple[str, str], None]:\n    parts = token.split(':')\n    if len(parts) == 1:\n        return '127.0.0.1', parts[0]\n    if len(parts) == 2:\n        return parts[0], parts[1]\n    return None","tryCatchPattern":"try:\n    ghidra_trace_listen(debugger, token, result, internal_dict)\nexcept RuntimeError as e:\n    if str(e) == 'ADDRESS must be PORT or HOST:PORT':\n        # reduce to PORT or HOST:PORT (drop IPv6 / extra colons)\n        ...\n    raise","preventionTips":["Use a bare PORT or a single HOST:PORT token for listen","Avoid raw IPv6 literals on this path","Quote the token if it could contain spaces"],"tags":["network","ghidra","lldb","cli","validation","connection","ipv6"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}