[Bug]: Passing invalid parameters to gemini throws Undefined array key "choices" /www/htdocs/vendor/openai-php/client/src/Responses/Chat/CreateResponse.php 54
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
To confirm. This is an HTTP/200 with that body?
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. 🙂