NationalSecurityAgency/ghidra · error · RuntimeError

address must be 'port' or 'host:port'

Error message

address must be 'port' or 'host:port'

What it means

Raised by ghidra_trace_listen (commands.py:196-202) when address.split(':') yields neither 1 nor 2 parts. listen is more permissive than connect (a bare port maps to 127.0.0.1), but three or more colon-separated tokens are rejected.

Source

Thrown at Ghidra/Debug/Debugger-agent-x64dbg/src/main/py/src/ghidraxdbg/commands.py:202

def ghidra_trace_listen(address: str = '127.0.0.1:0') -> None:
    """Listen for Ghidra to connect for tracing.

    Takes an optional address for the host and port on which to listen.
    Either the form 'host:port' or just 'port'. If omitted, it will bind
    to an ephemeral port on localhost. If only the port is given, it will
    bind to that port on localhost. This command will block until the
    connection is established.
    """

    STATE.require_no_client()
    parts = address.split(':')
    if len(parts) == 1:
        host, port = '127.0.0.1', parts[0]
    elif len(parts) == 2:
        host, port = parts
    else:
        raise RuntimeError("address must be 'port' or 'host:port'")

    try:
        s = socket.socket()
        s.bind((host, int(port)))
        host, port = s.getsockname()
        s.listen(1)
        print("Listening at {}:{}...".format(host, port))
        c, (chost, cport) = s.accept()
        s.close()
        print("Connection from {}:{}".format(chost, cport))
        STATE.client = Client(c, "x64dbg", methods.REGISTRY)
    except ValueError:
        raise RuntimeError("port must be numeric")


def ghidra_trace_disconnect() -> None:
    """Disconnect Python from Ghidra for tracing."""

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Use a bare port ('12345') or host:port ('127.0.0.1:12345') only.
  2. Normalize IPv6 or multi-colon input to a two-token host:port before calling.
  3. If forwarding user input, reject values where address.split(':') length is > 2 upstream.

Example fix

// before
ghidra_trace_listen('host:port:extra')

// after
ghidra_trace_listen('12345')
Defensive patterns

Strategy: validation

Validate before calling

def normalize_listen_address(s: str) -> str:
    parts = s.split(':')
    if len(parts) > 2:
        raise ValueError(f"listen address must be 'port' or 'host:port', got {s!r}")
    return s

ghidra_trace_listen(normalize_listen_address(raw))

Type guard

def is_listen_address(s: str) -> bool:
    return isinstance(s, str) and len(s.split(':')) <= 2

Try / catch

try:
    ghidra_trace_listen(address)
except RuntimeError as e:
    if "'port' or 'host:port'" in str(e):
        # fall back to port-only on localhost
        port = address.split(':')[-1]
        ghidra_trace_listen(port)
    else:
        raise

Prevention

When it happens

Trigger: Calling ghidra_trace_listen('a:b:c') (3 parts), an empty string (split gives [''], which is 1 part and would NOT trigger this), or any address with 2+ colons. Note: 1 or 2 parts are accepted.

Common situations: Passing an IPv6 address with multiple colons; a copy/paste that concatenated host:port:extra; a default-argument override that introduced extra colons.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/6bd785d59f3bd10e. Report an issue: GitHub.