bytebase/bytebase · error

invalid Google Chat webhook path: %s

Error message

invalid Google Chat webhook path: %s

What it means

Google Chat webhook URLs must have the exact path shape /v1/spaces/<space-id>/messages. validateGoogleChatURL splits the path into 5 segments and checks the literal v1, spaces, and messages segments plus a non-empty space ID.

Source

Thrown at backend/plugin/webhook/validator.go:116

					return validateGoogleChatURL(u)
				}
				return nil
			}
		}
	}

	return errors.Errorf("webhook URL domain %q is not allowed for webhook type %s (allowed domains: %v)",
		hostname, webhookType, allowedDomainsForType)
}

func validateGoogleChatURL(u *url.URL) error {
	if u.Scheme != "https" {
		return errors.Errorf("invalid Google Chat URL scheme: %s (only https is allowed)", u.Scheme)
	}

	parts := strings.Split(u.Path, "/")
	if len(parts) != 5 || parts[1] != "v1" || parts[2] != "spaces" || parts[3] == "" || parts[4] != "messages" {
		return errors.Errorf("invalid Google Chat webhook path: %s", u.Path)
	}

	query := u.Query()
	if query.Get("key") == "" {
		return errors.Errorf("missing Google Chat webhook key")
	}
	if query.Get("token") == "" {
		return errors.Errorf("missing Google Chat webhook token")
	}

	return nil
}

// URLSupportsDirectMessage reports whether a webhook URL's endpoint form can
// carry a direct message to the users an event mentions, rather than only a
// post to the channel the URL names.
//
// The one form that cannot is a Microsoft Teams Power Automate workflow

View on GitHub (pinned to 1870550677)

Solutions

  1. Use the exact webhook URL from Chat space Settings > Apps & integrations > Webhooks (format https://chat.googleapis.com/v1/spaces/<ID>/messages?key=...&token=...)
  2. Remove extra path segments (thread keys, trailing slashes) after /messages
  3. Ensure the space ID between /spaces/ and /messages is present and unmodified
  4. If Google ships a new path format, update validateGoogleChatURL in backend/plugin/webhook/validator.go

Example fix

// before
url := "https://chat.googleapis.com/v1/spaces/AAAA/messages/threads/1?key=k&token=t"
// after
url := "https://chat.googleapis.com/v1/spaces/AAAA/messages?key=k&token=t"
Defensive patterns

Strategy: validation

Validate before calling

var googleChatPathRe = regexp.MustCompile(`^/v1/spaces/[^/]+/messages$`)
func looksLikeGoogleChatWebhook(raw string) bool {
	u, err := url.Parse(raw)
	return err == nil && u.Hostname() == "chat.googleapis.com" && googleChatPathRe.MatchString(u.Path)
}

Type guard

func isGoogleChatWebhookURL(raw string) bool {
	u, err := url.Parse(raw)
	if err != nil || u.Scheme != "https" { return false }
	parts := strings.Split(u.Path, "/")
	return len(parts) == 5 && parts[1] == "v1" && parts[2] == "spaces" && parts[3] != "" && parts[4] == "messages"
}

Try / catch

if err := webhook.ValidateWebhookURL(raw, "googlechat"); err != nil {
	if strings.Contains(err.Error(), "invalid Google Chat webhook path") {
		return fmt.Errorf("URL must be https://chat.googleapis.com/v1/spaces/<id>/messages")
	}
	return err
}

Prevention

When it happens

Trigger: Saving a Google Chat URL whose path deviates from /v1/spaces/{id}/messages — wrong number of segments, wrong API version, a thread-style URL with extra segments, missing space ID, or a non-Google-Chat URL pasted into the Google Chat webhook field.

Common situations: Copying the URL from the browser instead of the webhook dialog (e.g. including ?threadKey or trailing segments); Google changing the API surface (v1 vs future versions); pasting a Chat API resource name like spaces/AAA into a bare URL; URL-encoding issues mangling slashes.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/23a9f448a45980eb. Report an issue: GitHub.