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

  1. Read the status and body in the error: fix the specific cause reported by the API (permission denied, not found, etc.).
  2. Enable the Conversational Analytics API (`gcloud services enable cloudaicompanion.googleapis.com`) in the project.
  3. Grant the caller (service account/user) the required IAM role (e.g. Cloud AI Companion User) on the project.
  4. Verify the BigQuery source's project and location match the datasets being referenced.
  5. 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

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


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/ff9ba2a59c63a7d1. Report an issue: GitHub.