{"record":{"id":"9eb0af63f2df78bf","repo":"w7corp/easywechat","slug":"response-body-is-empty","errorCode":null,"errorMessage":"Response body is empty.","messagePattern":"Response body is empty\\.","errorType":"exception","errorClass":"BadResponseException","httpStatus":null,"severity":"error","filePath":"src/Kernel/HttpClient/Response.php","lineNumber":98,"sourceCode":"            return (bool) ($this->failureJudge)($this);\n        }\n\n        try {\n            return $this->getStatusCode() >= 400;\n        } catch (Throwable $e) {\n            return true;\n        }\n    }\n\n    /**\n     * @throws BadResponseException\n     */\n    public function toArray(?bool $throw = null): array\n    {\n        $throw ??= $this->throw;\n\n        if ('' === $content = $this->response->getContent($throw)) {\n            throw new BadResponseException('Response body is empty.');\n        }\n\n        $contentType = $this->getHeaderLine('content-type', $throw);\n\n        if (str_contains($contentType, 'text/xml')\n            || str_contains($contentType, 'application/xml')\n            || str_starts_with($content, '<xml>')) {\n            try {\n                return Xml::parse($content) ?? [];\n            } catch (Throwable $e) {\n                throw new BadResponseException('Response body is not valid xml.', 400, $e);\n            }\n        }\n\n        return $this->response->toArray($throw);\n    }\n\n    public function toJson(?bool $throw = null): string|false","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/w7corp/easywechat/blob/f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8/src/Kernel/HttpClient/Response.php#L80-L116","documentation":"Response::toArray() requires a non-empty body: it calls the underlying Symfony response's getContent($throw) and throws BadResponseException('Response body is empty.') when the content is ''. The HTTP exchange completed but returned zero bytes — empty 2xx, an error status with an empty body (when throw=false), or a proxied response with no payload.","triggerScenarios":"Calling toArray() on a media/binary download response, on a response whose status is 3xx/4xx/5xx with empty body (e.g. after getStatusCode() was not checked), or on a callback verification GET request that WeChat answers with an empty echo body.","commonSituations":"Using toArray() where saveAs() is needed (downloads), gateways/proxies stripping error bodies, WeChat returning empty body on some rate-limit/refused paths, following redirects to empty endpoints.","solutions":["Check the status code first: $response->getStatusCode() and $response->getContent(false) before parsing","Use saveAs($path) for binary/media downloads instead of toArray()","Log the raw exchange (url, status, headers) when it fires to identify the empty-body source"],"exampleFix":"// before\n$data = $response->toArray(); // throws when body is empty\n\n// after\nif ($response->getStatusCode() !== 200 || '' === $response->getContent(false)) {\n    throw new RuntimeException('Unexpected empty response: HTTP '.$response->getStatusCode());\n}\n$data = $response->toArray();","handlingStrategy":"validation","validationCode":"// Guard before parsing\n$content = $response->getContent(false);\nif ('' === $content) {\n    $status = $response->getStatusCode();\n    throw new RuntimeException(\"WeChat returned an empty body (HTTP {$status})\");\n}\n$data = $response->toArray();","typeGuard":null,"tryCatchPattern":"try {\n    $data = $response->toArray();\n} catch (\\Symfony\\Component\\HttpClient\\Exception\\BadResponseException $e) {\n    if (str_contains($e->getMessage(), 'empty')) {\n        // empty body: decide per endpoint (retry / treat as error / ignore)\n        $data = [];\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Always check status code and content before parsing WeChat responses","Use saveAs() for binary downloads; never toArray() on media endpoints","Alert on empty-body rates — they usually indicate gateway trouble"],"tags":["php","easywechat","http-client","response-handling","empty-body"],"backgroundTag":"empty-response-body","analyzedSha":"f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8","analyzedAt":"2026-08-21T05:29:19.565Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}