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:199-205) when the address splits into other than 1 or 2 parts. Unlike connect, listen accepts either a bare 'port' (bound on 127.0.0.1) or 'host:port', but rejects addresses with two or more colons (IPv6 literals) or empty/whitespace inputs that produce unexpected counts.

Source

Thrown at Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py:205

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, "dbgeng.dll", 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. Pass either 'port' or 'host:port' with a single colon, e.g. '12345' or '0.0.0.0:12345'.
  2. For IPv6, fall back to a hostname or IPv4 binding.
  3. Trim whitespace and strip any scheme/brackets before calling.

Example fix

// before
ghidra_trace_listen('[::1]:12345')   # 3 parts after split

// after
ghidra_trace_listen('12345')           # binds 127.0.0.1:12345
Defensive patterns

Strategy: validation

Validate before calling

def validate_listen_address(address):
    parts = address.split(':')
    if len(parts) not in (1, 2):
        raise ValueError("address must be 'port' or 'host:port'")
    return parts

validate_listen_address(address)
ghidra_trace_listen(address)

Type guard

def is_listen_address(address) -> bool:
    if not isinstance(address, str):
        return False
    return len(address.split(':')) in (1, 2)

Try / catch

try:
    ghidra_trace_listen(address)
except RuntimeError as e:
    if "must be 'port' or 'host:port'" in str(e):
        raise ValueError('reformat the listen address') from e
    raise

Prevention

When it happens

Trigger: Passing an IPv6 literal like '[::1]:12345' (3 parts); passing 'a:b:c'; passing an empty string with an unexpected number of colons; passing a value with leading/trailing colons.

Common situations: IPv6 listening address where the bracket form was not stripped; misformatted config; copy/paste including a scheme prefix.

Related errors


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