{"id":"586bea9a7db4362d","repo":"redis/redis-py","slug":"provide-either-json-body-or-data-not-both","errorCode":null,"errorMessage":"Provide either json_body or data, not both.","messagePattern":"Provide either json_body or data, not both\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"redis/http/http_client.py","lineNumber":356,"sourceCode":"        resp = self.request(\n            method=method,\n            path=path,\n            params=params,\n            headers=headers,\n            body=body,\n            timeout=timeout,\n        )\n        if not (200 <= resp.status < 400):\n            raise HttpError(resp.status, resp.url, resp.text())\n        if expect_json:\n            return resp.json()\n        return resp\n\n    def _prepare_body(\n        self, json_body: Optional[Any] = None, data: Optional[Union[bytes, str]] = None\n    ) -> Optional[Union[bytes, str]]:\n        if json_body is not None and data is not None:\n            raise ValueError(\"Provide either json_body or data, not both.\")\n        if json_body is not None:\n            return json.dumps(json_body, ensure_ascii=False, separators=(\",\", \":\"))\n        return data\n\n    def _build_url(\n        self,\n        path: str,\n        params: Optional[\n            Mapping[str, Union[None, str, int, float, bool, list, tuple]]\n        ] = None,\n    ) -> str:\n        url = urljoin(self.base_url or \"\", path)\n        if params:\n            # urlencode with doseq=True supports list/tuple values\n            query = urlencode(\n                {k: v for k, v in params.items() if v is not None}, doseq=True\n            )\n            separator = \"&\" if (\"?\" in url) else \"?\"","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/http/http_client.py#L338-L374","documentation":"Raised as ValueError by HttpClient._prepare_body (redis/http/http_client.py:356) when both json_body and data are supplied to the same request. The two arguments produce the request body in mutually exclusive ways (json_body is JSON-serialized, data is sent verbatim), so providing both is ambiguous and rejected immediately rather than picking one silently.","triggerScenarios":"Calling client.post/put/patch(..., json_body=obj, data=raw) on the HttpClient with both arguments non-None.","commonSituations":"Refactoring a call from raw bytes to JSON and leaving the old data= argument in place; passing a pre-serialized JSON string as data alongside json_body; copy-paste between endpoints.","solutions":["Pass only one of json_body or data per request.","If you have pre-serialized JSON, pass it as data and drop json_body.","If you have a Python object, pass json_body and drop data.","Audit call sites after migrating between the two body styles."],"exampleFix":"// before\nclient.post('/items', json_body={'k': 1}, data=b'already-serialized')\n\n// after\nclient.post('/items', json_body={'k': 1})","handlingStrategy":"validation","validationCode":"if json_body is not None and data is not None:\n    raise ValueError('pass json_body OR data, not both')\nclient.post('/items', json_body=json_body, data=data)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass exactly one body argument per request: json_body for objects, data for pre-serialized bytes.","When migrating from raw bytes to JSON, remove the old data= argument.","Audit call sites after changing the body style to catch leftover arguments."],"tags":["http","httpclient","validation","valueerror"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}