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
- Read the body in the error message — it contains the Google API error JSON with the precise cause
- For 401/403, refresh credentials and grant the monitoring viewer role
- For 429, implement backoff and reduce request rate
- 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
- Parse the embedded body JSON to distinguish auth vs quota vs syntax errors
- Grant monitoring.viewer to the service account
- Implement exponential backoff for 429/5xx
- Validate MQL syntax against documented examples before deployment
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
- status %d %s: %s
- failed to read response body: %w
- failed to unmarshal json: %w, body: %s
- request failed with status %s: %s
- get_schema API error (status %d): %s
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/8ee24be00217f490.
Report an issue: GitHub.