Thanks for your work and apologies for all the back and forth, we're close!  The last commit wasn't quite what I had in mind, here's what I was thinking:

```python
def _data_callback(self, conn, raw_data):
    conn.last_recv_timestamp = time.time()
    response = None
    error = None
    frame, data = nsq.unpack_response(raw_data)
    if frame == nsq.FRAME_TYPE_RESPONSE and data == "_heartbeat_":
        logging.info("[%s] received heartbeat", conn.id)
        self.heartbeat(conn)
        conn.send(nsq.nop())
    elif frame == nsq.FRAME_TYPE_RESPONSE:
        response = data
    elif frame == nsq.FRAME_TYPE_ERROR:
        logging.error("[%s] ERROR: %s", conn.id, data)
        error = NSQError(data)

    if (response or error) and conn.callback_queue:
        callback = conn.callback_queue.pop(0)
        callback(conn, response, error)
```

This way there is only ever one parameter set on the callback.  Callbacks would look like this:

```python
def callback(conn, response, error):
    if error:
        logging.error("blablabla")
```

(this implies changes in the few other spots where you're handling callbacks)