bytebase/bytebase · error
failed to POST Google Chat webhook, status code: %d, respons
Error message
failed to POST Google Chat webhook, status code: %d, response body: %s
What it means
This error is returned when the Google Chat webhook endpoint replies with a non-2xx HTTP status code. postMessage reads the whole response body and embeds both the status code and the raw body in the message, so the caller can see exactly what Google Chat rejected and why. It is a server-side rejection of the POST, not a transport failure.
Source
Thrown at backend/plugin/webhook/googlechat/googlechat.go:216
return errors.New("failed to construct Google Chat webhook POST request")
}
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
client := &http.Client{
Timeout: webhook.Timeout,
}
resp, err := client.Do(req)
if err != nil {
return errors.New("failed to POST Google Chat webhook")
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
return errors.New("failed to read Google Chat webhook response")
}
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
return errors.Errorf("failed to POST Google Chat webhook, status code: %d, response body: %s", resp.StatusCode, b)
}
return nil
}
func marshal(post MessagePayload) ([]byte, error) {
var body bytes.Buffer
encoder := json.NewEncoder(&body)
encoder.SetEscapeHTML(false)
if err := encoder.Encode(post); err != nil {
return nil, err
}
return bytes.TrimSpace(body.Bytes()), nil
}
View on GitHub (pinned to 1870550677)
Solutions
- Read the status code and body in the error to identify the rejection reason (404 = bad URL, 403 = revoked webhook, 429 = rate limited).
- Re-create the Google Chat space webhook in the Chat UI and update the stored webhook URL, since deleted/rotated webhooks return 403/404.
- Verify the configured URL matches the full https://chat.googleapis.com/v1/spaces/.../messages?key=...&token=... form.
- If 429, reduce notification frequency or batch events before retrying with backoff.
Example fix
// before URL: "https://chat.googleapis.com/v1/spaces/OLD_SPACE_ID/messages?key=oldKey" // returns 404 not found // after URL: "https://chat.googleapis.com/v1/spaces/AAAA-newSpace/messages?key=newKey&token=newToken" // returns 200 OK
Defensive patterns
Strategy: retry
Validate before calling
// Before saving the webhook URL, ping it:
func validateChatWebhook(u string) error {
req, _ := http.NewRequest(http.MethodPost, u, bytes.NewBufferString(`{"text":"test"}`))
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
resp, err := http.DefaultClient.Do(req)
if err != nil { return err }
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 { return fmt.Errorf("webhook returned %d", resp.StatusCode) }
return nil
} Type guard
func isWebhookStatusError(err error) (int, string, bool) {
var n, msg string
_, scanErr := fmt.Sscanf(err.Error(), "failed to POST Google Chat webhook, status code: %d", new(int))
_ = n; _ = msg; _ = scanErr
return 0, "", strings.Contains(err.Error(), "status code:")
} Try / catch
if err := googlechat.Post(ctx); err != nil {
var status int
if n, _ := fmt.Sscanf(err.Error(), "failed to POST Google Chat webhook, status code: %d", &status); n == 1 {
switch {
case status == 429:
time.Sleep(backoff); retry()
case status == 404 || status == 403:
alertOwnerToRecreateWebhook(err)
}
}
return err
} Prevention
- Validate the webhook URL with a test POST when saving integration settings
- Treat 403/404 as 'webhook deleted' and alert the admin to re-create it
- Retry only 5xx/429 with exponential backoff; never retry 4xx permanently
- Monitor for recurring non-2xx to detect silently revoked webhooks
When it happens
Trigger: postMessage POSTs the marshaled message to context.URL via client.Do, gets a response with StatusCode < 200 or >= 300, and formats the status plus response body into this error.
Common situations: The webhook URL was revoked or mistyped (404), the Google Chat space webhook was deleted (403/404), an invalid or truncated webhook URL/key is configured, or Google rate-limits the space (429).
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- failed to construct Google Chat webhook POST request
- failed to POST Google Chat webhook
- failed to read Google Chat webhook response
- missing authorization token
- failed to get workspace profile setting
AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06).
Data as JSON: /api/errors/72dac730e340362f.
Report an issue: GitHub.