w7corp/easywechat · warning · BadMethodCallException

%s does't implements %s

Error message

%s does't implements %s

What it means

Response::toStream() can only stream when the wrapped Symfony response implements StreamableInterface; the fallback path (used for MockResponse and other non-streamable responses) returns a mock stream when $throw is falsy, but throws BadMethodCallException("<class> does't implements ...") when $throw is true. The library is telling you the concrete response class cannot provide a PHP stream resource.

Source

Thrown at src/Kernel/HttpClient/Response.php:133

    public function toJson(?bool $throw = null): string|false
    {
        return json_encode($this->toArray($throw), JSON_UNESCAPED_UNICODE);
    }

    /**
     * {@inheritdoc}
     *
     * @throws BadMethodCallException
     */
    public function toStream(?bool $throw = null)
    {
        if ($this->response instanceof StreamableInterface) {
            return $this->response->toStream($throw ?? $this->throw);
        }

        if ($throw) {
            throw new BadMethodCallException(sprintf('%s does\'t implements %s', \get_class($this->response), StreamableInterface::class));
        }

        return StreamWrapper::createResource(new MockResponse);
    }

    /**
     * @throws \LogicException
     */
    public function toDataUrl(): string
    {
        return 'data:'.$this->getHeaderLine('content-type').';base64,'.base64_encode($this->getContent());
    }

    public function toPsrResponse(?ResponseFactoryInterface $responseFactory = null, ?StreamFactoryInterface $streamFactory = null): \Psr\Http\Message\ResponseInterface
    {
        $streamFactory ??= $responseFactory instanceof StreamFactoryInterface ? $responseFactory : null;

        if ($responseFactory === null || $streamFactory === null) {

View on GitHub (pinned to f0cf0a8b83)

Solutions

  1. Do not pass true: call $response->toStream() and let it fall back when streaming is unsupported
  2. In tests, provide a response that implements StreamableInterface if you need a real stream
  3. For large downloads prefer saveAs($path) or toDataUrl() over streaming

Example fix

// before
$stream = $response->toStream(true); // throws for MockResponse

// after
$stream = $response->toStream(); // mock fallback, no exception
Defensive patterns

Strategy: try-catch

Try / catch

try {
    $stream = $response->toStream(true);
} catch (\BadMethodCallException $e) {
    // underlying response (e.g. MockResponse in tests) cannot stream
    $stream = $response->toStream(); // mock fallback
}

Prevention

When it happens

Trigger: Calling toStream(true) on a Response wrapping a Symfony HttpClient MockResponse (unit tests) or any response class lacking StreamableInterface.

Common situations: Test suites mocking HttpClient responses, custom response wrappers injected into the client, code paths that force throw=true unconditionally.

Related errors


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