{"record":{"id":"7045ca934e2f29de","repo":"pika/pika","slug":"write-called-with-empty-data-data-r","errorCode":null,"errorMessage":"write() called with empty data {data!r}","messagePattern":"write\\(\\) called with empty data (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"pika/adapters/utils/io_services_utils.py","lineNumber":787,"sourceCode":"\n    @override\n    def get_write_buffer_size(self) -> int:\n        \"\"\"\n        :returns: Current size of output data buffered by the transport\n        \"\"\"\n        return self._tx_buffered_byte_count\n\n    def _buffer_tx_data(self, data: bytes) -> None:\n        \"\"\"\n        Buffer the given data until it can be sent asynchronously.\n\n        :param data:\n        :raises ValueError: if called with empty data\n        \"\"\"\n        if not data:\n            _LOGGER.error('write() called with empty data: state=%s; %s',\n                          self._state, self._sock)\n            raise ValueError(f'write() called with empty data {data!r}')\n\n        if self._state != self._STATE_ACTIVE:\n            _LOGGER.debug(\n                'Ignoring write() called during inactive state: '\n                'state=%s; %s', self._state, self._sock)\n            return\n\n        self._tx_buffers.append(data)\n        self._tx_buffered_byte_count += len(data)\n\n    def _consume(self) -> None:\n        \"\"\"\n        Utility method for use by subclasses to ingest data from socket and dispatch it to\n        protocol's `data_received()` method socket-specific \"try again\" exception, per-event data\n        consumption limit is reached, transport becomes inactive, or a fatal failure.\n\n        Consumes up to `self._MAX_CONSUME_BYTES` to prevent event starvation or until state becomes\n        inactive (e.g., `protocol.data_received()` callback aborts the transport)","sourceCodeStart":769,"sourceCodeEnd":805,"githubUrl":"https://github.com/pika/pika/blob/34a407b24f08f2307578ceff870b6d7a12e7fdca/pika/adapters/utils/io_services_utils.py#L769-L805","documentation":"_AsyncTransportBase._buffer_tx_data refuses to buffer an empty bytes payload, because queueing an empty write is wasteful and can spin event loops. This is an internal transport invariant; the public write path should never produce empty data. Hitting it usually means a framing bug or a caller sending b''.","triggerScenarios":"A transport/protocol caller invoking the internal write path with b'' or another falsy bytes value; a framing bug producing zero-length frames.","commonSituations":"Custom transport/protocol that flushes buffers even when empty; a bug in pika's own framing (rare). End users of the public API normally never hit this directly.","solutions":["Guard the write with `if data:` before calling the internal buffer path","Trace the upstream caller producing zero-length payloads","If using only pika's public API, file a bug - this signals an internal framing error"],"exampleFix":"# before\ntransport._buffer_tx_data(b'')  # ValueError\n\n# after\nif data:\n    transport._buffer_tx_data(data)","handlingStrategy":"validation","validationCode":"def safe_buffer(transport, data):\n    if data:  # skip empty payloads\n        transport._buffer_tx_data(data)\n\nsafe_buffer(transport, payload)","typeGuard":null,"tryCatchPattern":"try:\n    transport._buffer_tx_data(data)\nexcept ValueError as e:\n    if 'empty data' in str(e):\n        pass  # ignore empty write\n    else:\n        raise","preventionTips":["Guard internal writes with `if data:` before buffering","Avoid calling private transport buffer methods directly; use the public write path","If this surfaces from pika internals while using only public APIs, file a bug"],"tags":["io","internal","transport","invariant"],"backgroundTag":null,"analyzedSha":"34a407b24f08f2307578ceff870b6d7a12e7fdca","analyzedAt":"2026-08-07T23:58:35.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}