{"record":{"id":"aca6e5126392dda6","repo":"sgl-project/sglang","slug":"http-material-response-read-must-return-bytes-g","errorCode":null,"errorMessage":"HTTP material response.read() must return bytes, got {type(chunk).__name__}","messagePattern":"HTTP material response\\.read\\(\\) must return bytes, got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/material_io.py","lineNumber":745,"sourceCode":"        suffix = (\n            _safe_suffix(uri)\n            or _SUFFIX_BY_MEDIA_TYPE.get(str(media_type or \"\").lower())\n            or _DEFAULT_SUFFIX_BY_TYPE.get(condition_type, \".bin\")\n        )\n        output_path = (\n            Path(_material_workdir(batch))\n            / f\"condition_{int(condition_index):04d}{suffix}\"\n        )\n        partial_path = output_path.with_name(output_path.name + \".partial\")\n        total = 0\n        try:\n            with partial_path.open(\"wb\") as output:\n                while True:\n                    chunk = response.read(MINIMAX_H3_HTTP_READ_CHUNK_BYTES)\n                    if not chunk:\n                        break\n                    if not isinstance(chunk, bytes):\n                        raise TypeError(\n                            \"HTTP material response.read() must return bytes, got \"\n                            f\"{type(chunk).__name__}\"\n                        )\n                    total += len(chunk)\n                    output.write(chunk)\n            if total == 0:\n                raise ValueError(f\"HTTP material body is empty: {uri}\")\n            partial_path.replace(output_path)\n        except Exception:\n            partial_path.unlink(missing_ok=True)\n            output_path.unlink(missing_ok=True)\n            raise\n    return str(output_path)\n\n\ndef minimax_h3_localize_material_uri(\n    batch: Any,\n    uri: str,","sourceCodeStart":727,"sourceCodeEnd":763,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/material_io.py#L727-L763","documentation":"While downloading an HTTP(S) material, response.read(n) returned a non-bytes object (e.g. str). The downloader requires a bytes-returning file-like response body.","triggerScenarios":"A custom HTTP client / mocked response whose read() returns str, or a urllib opener wrapper that decodes bodies to text; hit inside _stream_http_material.","commonSituations":"Unit tests with MagicMock responses returning strings; custom opener installed via build_opener that text-decodes bodies.","solutions":["Ensure the response body is opened in binary mode with no text-decoding wrapper","In tests, mock read() to return b'...' not '...'","Remove any response-class override that decodes content"],"exampleFix":"# before\nmock_resp.read.return_value = 'PNGDATA'\n# after\nmock_resp.read.return_value = b'PNGDATA'","handlingStrategy":"type-guard","validationCode":"chunk = response.read(1)\nassert isinstance(chunk, bytes)","typeGuard":"def is_binary_response(resp) -> bool:\n    return isinstance(resp.read(1), bytes)","tryCatchPattern":"except TypeError as e: fix the HTTP client to return bytes","preventionTips":["Mock read() with bytes in tests","Don't wrap response bodies in text-decoding layers"],"tags":["http","type-error","mocking"],"backgroundTag":"http-response-type-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}