redis/redis-py · error · DataError

Passing a host requires passing a port, and vice versa

Error message

Passing a host requires passing a port, and vice versa

What it means

Raised as a DataError in the ClusterPubSub constructor when only one of host or port is provided (the other is None). The guard at cluster.py:3016-3018 uses any([host, port]) to detect the partial case. Both must be provided together or neither, because a node address requires both components to be meaningful.

Solutions

  1. Provide both host and port together: client.pubsub(host='10.0.0.1', port=7000).
  2. If you want the default node, pass neither: client.pubsub().
  3. If you have a ClusterNode, pass node= instead: client.pubsub(node=my_node).

Example fix

// before
ps = client.pubsub(host='10.0.0.1')

// after
ps = client.pubsub(host='10.0.0.1', port=7000)
Defensive patterns

Strategy: validation

Validate before calling

# Validate host/port are both provided or both absent
if bool(host) != bool(port):
    raise ValueError('Provide both host and port, or neither')

Type guard

def host_port_pair_valid(host, port) -> bool:
    return (host is not None) == (port is not None)

Try / catch

null

Prevention

When it happens

Trigger: Calling client.pubsub(host='10.0.0.1') without port, or client.pubsub(port=7000) without host. Either triggers the DataError.

Common situations: Developer passes a host string but forgets the port, or extracts host and port from a config object where one value is missing.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/627a83637c509908. Report an issue: GitHub.

Appendix: source

Thrown at redis/cluster.py:3018

        If host is passed without port, or vice versa, a DataError will be
        thrown.
        :type cluster: RedisCluster
        :type node: ClusterNode
        :type host: str
        :type port: int
        """
        if node is not None:
            # node is passed by the user
            self._raise_on_invalid_node(cluster, node, node.host, node.port)
            pubsub_node = node
        elif host is not None and port is not None:
            # host and port passed by the user
            node = cluster.get_node(host=host, port=port)
            self._raise_on_invalid_node(cluster, node, host, port)
            pubsub_node = node
        elif any([host, port]) is True:
            # only 'host' or 'port' passed
            raise DataError("Passing a host requires passing a port, and vice versa")
        else:
            # nothing passed by the user. set node to None
            pubsub_node = None

        self.node = pubsub_node

    def get_pubsub_node(self):
        """
        Get the node that is being used as the pubsub connection
        """
        return self.node

    def _raise_on_invalid_node(self, redis_cluster, node, host, port):
        """
        Raise a RedisClusterException if the node is None or doesn't exist in
        the cluster.
        """
        if node is None or redis_cluster.get_node(node_name=node.name) is None:

View on GitHub (pinned to 6a6b581b48)