alibaba / alibaba/open-code-review
Opaque "400 Bad Request" error with missing details when using Gemini / OpenAI-compatible endpoints
- Dominant language
- Go
- Stars
- 24.4k
- Forks
- 1.8k
- Avg merge
- 2d 4m
- Merged PRs (30d)
- 102
Description
### OpenCodeReview Version
open-code-review v1.9.8 (9c5e90d0) built at: 2026-08-20T02:32:42Z
### Operating System
macOS (Apple Silicon)
### Installation Method
npm (global)
### LLM Provider
Other OpenAI-compatible endpoint
### Bug Description
When an Google Gemini via OpenAI-compatible endpoint `https://generativelanguage.googleapis.com/v1beta/openai` returns an HTTP 400 Bad Request or other non-2xx error, the CLI and session logs only display `400 Bad Request` without the underlying JSON error details.
Because Google Gemini format their error details in nested fields (`details`, `fieldViolations`) rather than standard top-level fields, the default `*openai.Error.Error()` method omits the response payload. This leaves the user with no actionable error message to understand why the request failed.
### Steps to Reproduce
1. Configure an OpenAI-compatible provider pointing to Google Gemini (`https://generativelanguage.googleapis.com/v1beta/openai`) with a Gemini model (e.g., `gemini-3.6-flash`).
2. Run a review on changes that trigger an upstream parameter or schema validation error:
`ocr review --background "test background"`
3. The review fails on an LLM call with `400 Bad Request`.
4. Inspect the session file (`~/.opencodereview/sessions/.../*.jsonl`) or terminal error output.
5. Notice the error string only contains `400 Bad Request` with no raw response body or reason explanation.
### Expected Behavior
When the API returns an error response, OpenCodeReview should unwrap and display the raw JSON error payload / status / code from the HTTP response (e.g. via `apiErr.RawJSON()`), allowing users and logs to see the exact rejection reason from the vendor (such as field violations or invalid parameters).
### Logs / Error Output
```shell
[ocr] Subtask error for internal/llm/responses_client.go: LLM completion error: POST "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions": 400 Bad Request
```
### Additional Context
I was trying to setup Google Gemini API with `ocr`. The setup was successful, but running `ocr review ...` was failing and I couldn't figure out why from the logs.
Here's a stdout log before the change (similar is in the jsonl log):
```bash
[ocr] Subtask error for internal/llm/responses_client.go: LLM completion error: POST "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions": 400 Bad Request
```
Here's a stdout log after the change:
```bash
[ocr] Subtask error for internal/llm/client.go: LLM completion error: Google Gemini API error (HTTP 400 Bad Request, model: gemini-3.7-flash), response body: [{
"error": {
"code": 400,
"message": "Function call is missing a thought_signature in functionCall parts. This is required for tools to work correctly, and missing thought_signature may lead to degraded model performance. Additional data, function call `default_api:file_read_diff` , position 2. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures for more details.",
"status": "INVALID_ARGUMENT"
}
}
]: POST "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions": 400 Bad Request
```
(As you can see, this hints toward additional issue with Gemini API with thought_signatures).
Contributor guide
Research direction
Start in internal/llm/responses_client.go and internal/llm/client.go, tracing how non-2xx OpenAI-compatible responses become logged errors. Reproduce the Gemini endpoint failure and verify that the session log and terminal output include the raw JSON payload, HTTP status, and useful vendor error details.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100