{"record":{"id":"37d9bfc0b5a583e0","repo":"netdata/netdata","slug":"unbuffered-streams-must-be-binary","errorCode":null,"errorMessage":"unbuffered streams must be binary","messagePattern":"unbuffered streams must be binary","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/collectors/python.d.plugin/python_modules/urllib3/packages/backports/makefile.py","lineNumber":41,"sourceCode":"        )\n    writing = \"w\" in mode\n    reading = \"r\" in mode or not writing\n    assert reading or writing\n    binary = \"b\" in mode\n    rawmode = \"\"\n    if reading:\n        rawmode += \"r\"\n    if writing:\n        rawmode += \"w\"\n    raw = SocketIO(self, rawmode)\n    self._makefile_refs += 1\n    if buffering is None:\n        buffering = -1\n    if buffering < 0:\n        buffering = io.DEFAULT_BUFFER_SIZE\n    if buffering == 0:\n        if not binary:\n            raise ValueError(\"unbuffered streams must be binary\")\n        return raw\n    if reading and writing:\n        buffer = io.BufferedRWPair(raw, raw, buffering)\n    elif reading:\n        buffer = io.BufferedReader(raw, buffering)\n    else:\n        assert writing\n        buffer = io.BufferedWriter(raw, buffering)\n    if binary:\n        return buffer\n    text = io.TextIOWrapper(buffer, encoding, errors, newline)\n    text.mode = mode\n    return text\n","sourceCodeStart":23,"sourceCodeEnd":55,"githubUrl":"https://github.com/netdata/netdata/blob/4864de85e26f6734d92cfc27ccbeff5921f49938/src/collectors/python.d.plugin/python_modules/urllib3/packages/backports/makefile.py#L23-L55","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before\nf = wrapped_sock.makefile('r', buffering=0)\n# ValueError: unbuffered streams must be binary\n\n# after\nf = wrapped_sock.makefile('rb', buffering=0)\ndata = f.read().decode('utf-8')  # explicit decode","handlingStrategy":"validation","validationCode":"def open_sock_stream(sock, mode='r', buffering=-1, **kw):\n    if buffering == 0:\n        assert 'b' in mode, 'buffering=0 requires binary mode'\n        return sock.makefile(mode + ('b' if 'b' not in mode else ''), buffering=0)\n    return sock.makefile(mode, buffering=buffering, **kw)","typeGuard":"def unbuffered_ok(mode, buffering):\n    return buffering != 0 or 'b' in mode","tryCatchPattern":"try:\n    f = sock.makefile('r', buffering=0)\nexcept ValueError as e:\n    if 'unbuffered streams must be binary' in str(e):\n        f = sock.makefile('rb', buffering=0)\n    else:\n        raise","preventionTips":["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"],"tags":["python","urllib3","socket","makefile","buffering","io"],"backgroundTag":null,"analyzedSha":"4864de85e26f6734d92cfc27ccbeff5921f49938","analyzedAt":"2026-08-15T09:12:38.226Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}