googleapis/mcp-toolbox · error

request failed: %s, body: %s

Error message

request failed: %s, body: %s

What it means

RunQuery treats only HTTP 200 as success. Any other status code — 400 bad request, 401/403 auth problems, 404, 429 rate limits, 5xx server errors — produces this error, with the status line and the response body (which usually contains the Google API JSON error details) appended.

Source

Thrown at internal/sources/cloudmonitoring/cloud_monitoring.go:167

	q := req.URL.Query()
	q.Add("query", query)
	req.URL.RawQuery = q.Encode()

	req.Header.Set("User-Agent", s.UserAgent())

	resp, err := s.Client().Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response body: %w", err)
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("request failed: %s, body: %s", resp.Status, string(body))
	}

	if len(body) == 0 {
		return nil, nil
	}

	var result map[string]any
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("failed to unmarshal json: %w, body: %s", err, string(body))
	}

	return result, nil
}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Read the body in the error message — it contains the Google API error JSON with the precise cause
  2. For 401/403, refresh credentials and grant the monitoring viewer role
  3. For 429, implement backoff and reduce request rate
  4. For 400, validate the MQL/filter syntax and time range parameters

Example fix

// before
q := "fetch invalid::metric" // bad MQL
// after
q := "fetch gce_instance::compute.googleapis.com/instance/cpu/utilization"
Defensive patterns

Strategy: try-catch

Validate before calling

// validate MQL/filter and time range before calling RunQuery
if query == "" || startTime.After(endTime) {
    return fmt.Errorf("invalid monitoring query parameters")
}

Try / catch

result, err := src.RunQuery(ctx, query)
if err != nil {
    var apiErr struct {
        Error struct {
            Code    int    `json:"code"`
            Status  string `json:"status"`
            Message string `json:"message"`
        } `json:"error"`
    }
    if i := strings.Index(err.Error(), "body: {"); i >= 0 {
        if json.Unmarshal([]byte(err.Error()[i+6:]), &apiErr) == nil {
            switch apiErr.Error.Code {
            case 429: scheduleRetry()
            case 403: log.Printf("permission denied: %s", apiErr.Error.Message)
            }
        }
    }
    return err
}

Prevention

When it happens

Trigger: Executing a monitoring query whose HTTP response has a non-200 status: malformed query (MQL/TimeSeries filter), expired or insufficient-permission credentials, quota exhaustion, or GCP-side errors.

Common situations: Invalid Monitoring Query Language syntax; service account lacking monitoring.timeSeries.read permissions; hitting API quotas; project misconfiguration.

Related errors


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