{"record":{"id":"4874a375b121f05a","repo":"w7corp/easywechat","slug":"invalid-response-type-s","errorCode":null,"errorMessage":"Invalid Response type \"%s\".","messagePattern":"Invalid Response type \"(.+?)\"\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Kernel/Traits/RespondJsonMessage.php","lineNumber":43,"sourceCode":"\n    /**\n     * @throws InvalidArgumentException\n     */\n    protected function normalizeJsonResponse(mixed $response): array\n    {\n        if (! is_string($response) && is_callable($response)) {\n            $response = $response();\n        }\n\n        if (is_array($response)) {\n            if (! isset($response['msgtype'])) {\n                throw new InvalidArgumentException('msgtype cannot be empty.');\n            }\n\n            return $response;\n        }\n\n        throw new InvalidArgumentException(\n            sprintf('Invalid Response type \"%s\".', gettype($response))\n        );\n    }\n\n    /**\n     * @throws RuntimeException\n     */\n    protected function createJsonResponse(array $attributes, ?Encryptor $encryptor = null): ResponseInterface\n    {\n        $jsonStr = json_encode($attributes, JSON_UNESCAPED_UNICODE);\n\n        if (is_string($jsonStr)) {\n            return new Response(200, ['Content-Type' => 'application/json'], $encryptor ? $encryptor->encrypt($jsonStr, messageType: $this->messageType) : $jsonStr);\n        }\n\n        throw new InvalidArgumentException(\n            sprintf('Invalid Response content \"%s\".', implode(',', $attributes))\n        );","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/w7corp/easywechat/blob/f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8/src/Kernel/Traits/RespondJsonMessage.php#L25-L61","documentation":"In JSON reply mode (Work Server with messageType 'json'), the handler's return value — after invoking non-string callables — must be an array; strings, numbers, booleans and objects throw this InvalidArgumentException naming the actual gettype. Unlike XML mode (RespondXmlMessage), JSON mode never auto-wraps a plain string into a text reply; only empty values take the automatic 'success' no-op path.","triggerScenarios":"A Work JSON-mode handler does return 'ok';, return 200;, return true; or returns a DTO/object; anything that is not an array and not empty reaches the throw.","commonSituations":"One handler shared between OfficialAccount (XML, plain strings fine) and Work (JSON, arrays only); generic middleware handlers returning boolean 'handled' flags; returning the incoming Message object.","solutions":["Return an array with msgtype, wrapping strings as ['msgtype' => 'text', 'text' => ['content' => $value]].","Return '' or null when no reply is needed — the SDK answers 'success' itself.","Return a PSR-7 ResponseInterface to bypass normalization entirely."],"exampleFix":"// before: plain string in JSON reply mode\nreturn 'accepted';\n// after: array reply (or return '' to auto-answer 'success')\nreturn ['msgtype' => 'text', 'text' => ['content' => 'accepted']];","handlingStrategy":"validation","validationCode":"if (is_string($reply) || is_numeric($reply)) { $reply = ['msgtype' => 'text', 'text' => ['content' => (string) $reply]]; }\nif (!is_array($reply)) { throw new LogicException('JSON-mode handlers must return array/string/ResponseInterface/null'); }","typeGuard":"function isJsonReplyPayload(mixed $r): bool { return is_array($r) || is_string($r) || is_numeric($r) || $r === null || $r instanceof \\Psr\\Http\\Message\\ResponseInterface; }","tryCatchPattern":"try { return $server->serve(); } catch (\\EasyWeChat\\Kernel\\Exceptions\\InvalidArgumentException $e) { if (str_contains($e->getMessage(), 'Invalid Response type')) { \\Log::warning('handler returned non-array in JSON mode'); return new \\Nyholm\\Psr7\\Response(200, [], 'success'); } throw $e; }","preventionTips":["Document handler return contracts as array|ResponseInterface|null","Unit-test handler return shapes per reply mode","Do not share raw handlers between XML and JSON apps"],"tags":["php","wechat-work","json-reply","return-type"],"backgroundTag":"invalid-response-format","analyzedSha":"f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8","analyzedAt":"2026-08-21T05:29:19.565Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}