client icon indicating copy to clipboard operation
client copied to clipboard

[Bug]: Passing invalid parameters to gemini throws Undefined array key "choices" /www/htdocs/vendor/openai-php/client/src/Responses/Chat/CreateResponse.php 54

Open alxlab-zone66x opened this issue 3 months ago • 2 comments

Description

While testing gemini I noticed that passing invalid chat parameters doesn't throw the appropriate exception. It throws:

Undefined array key "choices" /www/htdocs/vendor/openai-php/client/src/Responses/Chat/CreateResponse.php 54

The reason the error isn't caught is because the error is returned as:

 array (
  0 =>
  array (
    'error' =>
    array (
      'code' => 400,
      'message' => 'Invalid JSON payload received. Unknown name "ddd": Cannot find field.',
      'status' => 'INVALID_ARGUMENT',
      'details' =>
      array (
        0 =>
        array (
          '@type' => 'type.googleapis.com/google.rpc.BadRequest',
          'fieldViolations' =>
          array (
            0 =>
            array (
              'description' => 'Invalid JSON payload received. Unknown name "ddd": Cannot find field.',
            ),
          ),
        ),
      ),
    ),
  ),
)

The HttpTransporter::throwIfJsonError() only checks for $response['error'], but in this case it's $response[0]['error'].

Steps To Reproduce

 $client  = \OpenAI::factory()
    ->withApiKey('YOUR-KEY')
    ->withBaseUri('https://generativelanguage.googleapis.com/v1beta/openai')
    ->make();
$result = $client->chat()->create($params = [
    'model' => 'gemini-2.5-flash',
    'messages' => [
        ['role' => 'system', 'content' => 'You can use tools if needed.'],
        ['role' => 'user', 'content' => 'Hello you.'],
    ],
    'ddd' => 'auto',
  ]);

OpenAI PHP Client Version

v0.16.1

PHP Version

8.2.5

Notes

No response

alxlab-zone66x avatar Oct 01 '25 23:10 alxlab-zone66x

To confirm. This is an HTTP/200 with that body?

iBotPeaches avatar Oct 01 '25 23:10 iBotPeaches

I'm assuming no since the following condition in HttpTransporter::throwIfJsonError() isn't met

if ($response->getStatusCode() < 400) {
    return;
}

I've already test hot fix in my project which fixed the problem. ie. outputs a proper exception and message:

private function throwIfJsonError(ResponseInterface $response, string|ResponseInterface $contents): void
    {
        if ($response->getStatusCode() < 400) {
            return;
        }

        if (! str_contains($response->getHeaderLine('Content-Type'), ContentType::JSON->value)) {
            return;
        }

        $statusCode = $response->getStatusCode();

        if ($contents instanceof ResponseInterface) {
            $contents = (string) $contents->getBody();
        }

        try {
            /** @var array{error?: array{message: string|array<int, string>, type: string, code: string}} $response */
            $response = json_decode($contents, true, flags: JSON_THROW_ON_ERROR);

            if (isset($response['error']) || isset( $response[0]['error'])) {
                throw new ErrorException($response['error'] ?? $response[0]['error'], $statusCode);
            }
        } catch (JsonException $jsonException) {
            throw new UnserializableResponse($jsonException);
        }
    }

That won't pass phpstan tests and I noticed that the latest commits have done changes to modified area.

I'll try to do a pull request tonight. I could use the practice. 🙂

alxlab-zone66x avatar Oct 01 '25 23:10 alxlab-zone66x