googleapis/mcp-toolbox · error
API returned non-200 status: %d %s
Error message
API returned non-200 status: %d %s
What it means
The Conversational Analytics `:chat` API responded with a status code other than 200; getStream reads the body and returns it inline so the caller can see the API's error message. Common statuses include 401/403 (auth/permissions), 404 (bad project/location), and 429/5xx (quota or server errors).
Source
Thrown at internal/tools/bigquery/bigqueryconversationalanalytics/bigqueryconversationalanalytics.go:291
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(payloadBytes))
if err != nil {
return "", fmt.Errorf("failed to create request: %w", err)
}
for k, v := range headers {
req.Header.Set(k, v)
}
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("failed to send request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return "", fmt.Errorf("API returned non-200 status: %d %s", resp.StatusCode, string(body))
}
var messages []map[string]any
decoder := json.NewDecoder(resp.Body)
dataMsgIdx := -1
// The response is a JSON array, so we read the opening bracket.
if _, err := decoder.Token(); err != nil {
if err == io.EOF {
return "", nil // Empty response is valid
}
return "", fmt.Errorf("error reading start of json array: %w", err)
}
for decoder.More() {
var rawMsg json.RawMessage
if err := decoder.Decode(&rawMsg); err != nil {
if err == io.EOF {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Read the status and body in the error: fix the specific cause reported by the API (permission denied, not found, etc.).
- Enable the Conversational Analytics API (`gcloud services enable cloudaicompanion.googleapis.com`) in the project.
- Grant the caller (service account/user) the required IAM role (e.g. Cloud AI Companion User) on the project.
- Verify the BigQuery source's project and location match the datasets being referenced.
- For 429/5xx, retry with exponential backoff; for 401, refresh credentials.
Example fix
// before: 403 PERMISSION_DENIED // gcloud projects add-iam-policy-binding MY_PROJECT \ // --member="serviceAccount:sa@project.iam.gserviceaccount.com" --role="roles/viewer" // after // gcloud projects add-iam-policy-binding MY_PROJECT \ // --member="serviceAccount:sa@project.iam.gserviceaccount.com" --role="roles/cloudaicompanion.user"
Defensive patterns
Strategy: try-catch
Validate before calling
cl, err := bigquery.NewClient(ctx, projectID)
if err != nil { return err }
_, err = cl.Dataset(datasetID).Metadata(ctx) // confirms project/dataset access
if err != nil { return fmt.Errorf("dataset inaccessible: %w", err) } Try / catch
result, err := tool.Invoke(ctx, params)
if err != nil && strings.Contains(err.Error(), "non-200 status") {
if strings.Contains(err.Error(), "403") {
return fmt.Errorf("grant roles/cloudaicompanion.user and enable cloudaicompanion.googleapis.com: %w", err)
}
return err
} Prevention
- Enable cloudaicompanion.googleapis.com in the target project before using the tool.
- Grant the caller the Conversational Analytics IAM role.
- Keep the source's project/location consistent with referenced datasets.
- Implement backoff on 429/5xx statuses.
When it happens
Trigger: Invoke on the tool when the GDA API rejects the request: missing cloudaicompanion.googleapis.com enablement, caller lacking the Conversational Analytics permission (e.g. roles/cloudaicompanion.user), wrong project/location in the URL, or exhausted quota.
Common situations: Service account without the required Conversational Analytics IAM role; API not enabled in the project; incorrect location (e.g. region mismatch with the BigQuery dataset); quota exceeded after heavy usage; VPC-SC perimeter rejection.
Related errors
- status %d %s: %s
- failed to send request: %w
- unable to execute query: %w
- request failed: %s, body: %s
- request failed with status %s: %s
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/ff9ba2a59c63a7d1.
Report an issue: GitHub.