w7corp/easywechat · error · InvalidArgumentException

Invalid Response content "%s".

Error message

Invalid Response content "%s".

What it means

createJsonResponse() json_encodes the reply attributes and throws this InvalidArgumentException when json_encode returns false. Encoding fails on malformed UTF-8 byte sequences and on NAN/INF values, so the usual culprit is reply content containing non-UTF-8 text (GBK/Latin-1 from a legacy database) or binary data. Note the message itself does implode(',', $attributes), which cannot render nested arrays.

Source

Thrown at src/Kernel/Traits/RespondJsonMessage.php:59

        }

        throw new InvalidArgumentException(
            sprintf('Invalid Response type "%s".', gettype($response))
        );
    }

    /**
     * @throws RuntimeException
     */
    protected function createJsonResponse(array $attributes, ?Encryptor $encryptor = null): ResponseInterface
    {
        $jsonStr = json_encode($attributes, JSON_UNESCAPED_UNICODE);

        if (is_string($jsonStr)) {
            return new Response(200, ['Content-Type' => 'application/json'], $encryptor ? $encryptor->encrypt($jsonStr, messageType: $this->messageType) : $jsonStr);
        }

        throw new InvalidArgumentException(
            sprintf('Invalid Response content "%s".', implode(',', $attributes))
        );
    }
}

View on GitHub (pinned to f0cf0a8b83)

Solutions

  1. Normalize reply text to UTF-8: mb_convert_encoding($text, 'UTF-8', 'GBK').
  2. Strip invalid sequences: iconv('UTF-8', 'UTF-8//IGNORE', $text).
  3. Keep floats out or guard with is_finite() before returning the reply.
  4. Never put binary in a passive reply — reply with a download link instead.

Example fix

// before: user text in GBK reaches the reply
return ['msgtype' => 'text', 'text' => ['content' => $userInput]];
// after: normalize to UTF-8 before replying
return ['msgtype' => 'text', 'text' => ['content' => mb_convert_encoding($userInput, 'UTF-8', 'GBK')]];
Defensive patterns

Strategy: validation

Validate before calling

array_walk_recursive($reply, function (&$v): void {
    if (is_string($v) && !mb_check_encoding($v, 'UTF-8')) { $v = mb_convert_encoding($v, 'UTF-8', 'GBK,UTF-8'); }
    if (is_float($v) && !is_finite($v)) { $v = 0; }
});

Type guard

function isUtf8JsonEncodable(array $reply): bool { $ok = true; array_walk_recursive($reply, function ($v) use (&$ok) { if (is_string($v)) { $ok = $ok && mb_check_encoding($v, 'UTF-8'); } }); return $ok; }

Try / catch

try { return $server->serve(); } catch (\EasyWeChat\Kernel\Exceptions\InvalidArgumentException $e) { if (str_contains($e->getMessage(), 'Invalid Response content')) { \Log::warning('reply not JSON-encodable, falling back to success'); return new \Nyholm\Psr7\Response(200, [], 'success'); } throw $e; }

Prevention

When it happens

Trigger: A Work JSON-mode passive reply whose text was stored or converted as GBK; echoing raw uploaded bytes into a reply; a division producing NAN/INF floats that end up in the payload.

Common situations: Databases with latin1/gbk columns feeding reply content; upstream systems sending unvalidated user text; debug strings appended to replies.

Related errors


AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21). Data as JSON: /api/errors/ce34cbc67364947b. Report an issue: GitHub.