netdata/netdata · error · ValueError
unbuffered streams must be binary
Error message
unbuffered streams must be binary
What it means
Same makefile backport, buffering branch: when buffering == 0 (unbuffered) the function can only return the raw SocketIO object, which is inherently binary. Requesting an unbuffered text stream (mode without 'b' together with buffering=0) is impossible to satisfy, so ValueError is raised before a broken stream object escapes.
Source
Thrown at src/collectors/python.d.plugin/python_modules/urllib3/packages/backports/makefile.py:41
)
writing = "w" in mode
reading = "r" in mode or not writing
assert reading or writing
binary = "b" in mode
rawmode = ""
if reading:
rawmode += "r"
if writing:
rawmode += "w"
raw = SocketIO(self, rawmode)
self._makefile_refs += 1
if buffering is None:
buffering = -1
if buffering < 0:
buffering = io.DEFAULT_BUFFER_SIZE
if buffering == 0:
if not binary:
raise ValueError("unbuffered streams must be binary")
return raw
if reading and writing:
buffer = io.BufferedRWPair(raw, raw, buffering)
elif reading:
buffer = io.BufferedReader(raw, buffering)
else:
assert writing
buffer = io.BufferedWriter(raw, buffering)
if binary:
return buffer
text = io.TextIOWrapper(buffer, encoding, errors, newline)
text.mode = mode
return text
View on GitHub (pinned to 4864de85e2)
Solutions
- Add 'b' to the mode when you need buffering=0, and decode/encode bytes explicitly at the call site
- Or keep text mode and accept default buffering (omit buffering or pass buffering=-1 / a positive int) — TextIOWrapper requires a buffer by design
- Wrap the raw binary stream manually: raw = sock.makefile('rb', buffering=0) then wrap with io.TextIOWrapper(io.BufferedReader(raw)) if you need both
Example fix
# before
f = wrapped_sock.makefile('r', buffering=0)
# ValueError: unbuffered streams must be binary
# after
f = wrapped_sock.makefile('rb', buffering=0)
data = f.read().decode('utf-8') # explicit decode Defensive patterns
Strategy: validation
Validate before calling
def open_sock_stream(sock, mode='r', buffering=-1, **kw):
if buffering == 0:
assert 'b' in mode, 'buffering=0 requires binary mode'
return sock.makefile(mode + ('b' if 'b' not in mode else ''), buffering=0)
return sock.makefile(mode, buffering=buffering, **kw) Type guard
def unbuffered_ok(mode, buffering):
return buffering != 0 or 'b' in mode Try / catch
try:
f = sock.makefile('r', buffering=0)
except ValueError as e:
if 'unbuffered streams must be binary' in str(e):
f = sock.makefile('rb', buffering=0)
else:
raise Prevention
- Never set buffering=0 without an explicit 'b' in the mode string
- Let buffering default (-1) unless profiling proves unbuffered IO is needed
- Wrap returned binary streams in TextIOWrapper explicitly when text semantics are required
When it happens
Trigger: Calling makefile('r', buffering=0) or makefile('w', buffering=0) — text mode with zero buffering — on a SecureTransport-wrapped socket (Python 3 path via urllib3's backport).
Common situations: Performance-tuning copy-paste that sets buffering=0 without realizing it forces binary; protocol code that handles the returned object as str and crashes later if the guard were absent; porting C-style unbuffered IO expectations to Python sockets.
Related errors
- invalid mode %r (only r, w, b allowed)
- 'cryptography' module missing required functionality. Try u
- 'pyOpenSSL' module missing required functionality. Try upgra
- SecureTransport only works on Pythons with memoryview
- SecureTransport only supports dumping binary certs
AI-assisted analysis of netdata/netdata@4864de85e2 (2026-08-15).
Data as JSON: /api/errors/37d9bfc0b5a583e0.
Report an issue: GitHub.