{"record":{"id":"23a9f448a45980eb","repo":"bytebase/bytebase","slug":"invalid-google-chat-webhook-path-s","errorCode":null,"errorMessage":"invalid Google Chat webhook path: %s","messagePattern":"invalid Google Chat webhook path: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/webhook/validator.go","lineNumber":116,"sourceCode":"\t\t\t\t\treturn validateGoogleChatURL(u)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn errors.Errorf(\"webhook URL domain %q is not allowed for webhook type %s (allowed domains: %v)\",\n\t\thostname, webhookType, allowedDomainsForType)\n}\n\nfunc validateGoogleChatURL(u *url.URL) error {\n\tif u.Scheme != \"https\" {\n\t\treturn errors.Errorf(\"invalid Google Chat URL scheme: %s (only https is allowed)\", u.Scheme)\n\t}\n\n\tparts := strings.Split(u.Path, \"/\")\n\tif len(parts) != 5 || parts[1] != \"v1\" || parts[2] != \"spaces\" || parts[3] == \"\" || parts[4] != \"messages\" {\n\t\treturn errors.Errorf(\"invalid Google Chat webhook path: %s\", u.Path)\n\t}\n\n\tquery := u.Query()\n\tif query.Get(\"key\") == \"\" {\n\t\treturn errors.Errorf(\"missing Google Chat webhook key\")\n\t}\n\tif query.Get(\"token\") == \"\" {\n\t\treturn errors.Errorf(\"missing Google Chat webhook token\")\n\t}\n\n\treturn nil\n}\n\n// URLSupportsDirectMessage reports whether a webhook URL's endpoint form can\n// carry a direct message to the users an event mentions, rather than only a\n// post to the channel the URL names.\n//\n// The one form that cannot is a Microsoft Teams Power Automate workflow","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/webhook/validator.go#L98-L134","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use the exact webhook URL from Chat space Settings > Apps & integrations > Webhooks (format https://chat.googleapis.com/v1/spaces/<ID>/messages?key=...&token=...)","Remove extra path segments (thread keys, trailing slashes) after /messages","Ensure the space ID between /spaces/ and /messages is present and unmodified","If Google ships a new path format, update validateGoogleChatURL in backend/plugin/webhook/validator.go"],"exampleFix":"// before\nurl := \"https://chat.googleapis.com/v1/spaces/AAAA/messages/threads/1?key=k&token=t\"\n// after\nurl := \"https://chat.googleapis.com/v1/spaces/AAAA/messages?key=k&token=t\"","handlingStrategy":"validation","validationCode":"var googleChatPathRe = regexp.MustCompile(`^/v1/spaces/[^/]+/messages$`)\nfunc looksLikeGoogleChatWebhook(raw string) bool {\n\tu, err := url.Parse(raw)\n\treturn err == nil && u.Hostname() == \"chat.googleapis.com\" && googleChatPathRe.MatchString(u.Path)\n}","typeGuard":"func isGoogleChatWebhookURL(raw string) bool {\n\tu, err := url.Parse(raw)\n\tif err != nil || u.Scheme != \"https\" { return false }\n\tparts := strings.Split(u.Path, \"/\")\n\treturn len(parts) == 5 && parts[1] == \"v1\" && parts[2] == \"spaces\" && parts[3] != \"\" && parts[4] == \"messages\"\n}","tryCatchPattern":"if err := webhook.ValidateWebhookURL(raw, \"googlechat\"); err != nil {\n\tif strings.Contains(err.Error(), \"invalid Google Chat webhook path\") {\n\t\treturn fmt.Errorf(\"URL must be https://chat.googleapis.com/v1/spaces/<id>/messages\")\n\t}\n\treturn err\n}","preventionTips":["Use the exact webhook URL from Chat's webhook dialog, not the browser address bar","Strip thread/extra path segments — keep only /v1/spaces/<id>/messages","Check for URL-encoding or truncation issues when the URL passes through other tools"],"tags":["url","validation","google-chat"],"backgroundTag":"invalid-url-format","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}