{"record":{"id":"974f646aba9daf68","repo":"bytebase/bytebase","slug":"missing-google-chat-webhook-key","errorCode":null,"errorMessage":"missing Google Chat webhook key","messagePattern":"missing Google Chat webhook key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/webhook/validator.go","lineNumber":121,"sourceCode":"\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\n// endpoint. teams.Post routes on the same fact at delivery time, and it decides\n// the question before the URL does: a webhook with direct messages enabled and\n// mentioned users sends them and returns, so the workflow post never happens.\n// Enabling it on a Power Automate webhook therefore diverts the customer's\n// notifications away from the flow they built, which is why the console hides","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/webhook/validator.go#L103-L139","documentation":"Validation in validateGoogleChatURL: fires when the https URL has a valid /v1/spaces/{id}/messages path but lacks the required key query parameter, meaning it is not a genuine Google Chat webhook URL.","triggerScenarios":"The URL path parses as /v1/spaces/<id>/messages but query.Get(\"key\") returns empty — the key= parameter was stripped during copy/paste, the URL was truncated at the token, or a sanitizer removed query parameters.","commonSituations":"Sharing the webhook URL through chat/email tools that trim query strings; pasting only the path portion; a config templating system URL-encoding or dropping &-separated params; partially redacted URLs from screenshots.","solutions":["Re-copy the complete webhook URL including ?key=...&token=... from Google Chat's webhook configuration","Verify nothing (proxy, log redaction, config template) strips query parameters","If the key was truly lost, delete and recreate the webhook in Google Chat to get a fresh URL","Add frontend validation checking for key and token params before submitting"],"exampleFix":"// before\nurl := \"https://chat.googleapis.com/v1/spaces/AAAA/messages?token=t\"\n// after\nurl := \"https://chat.googleapis.com/v1/spaces/AAAA/messages?key=k&token=t\"","handlingStrategy":"validation","validationCode":"u, err := url.Parse(raw)\nif err != nil { return err }\nif u.Query().Get(\"key\") == \"\" {\n\treturn errors.New(\"Google Chat webhook URL must include the key query parameter\")\n}","typeGuard":"func hasGoogleChatKey(raw string) bool {\n\tu, err := url.Parse(raw)\n\treturn err == nil && u.Query().Get(\"key\") != \"\"\n}","tryCatchPattern":"if err := webhook.ValidateWebhookURL(raw, \"googlechat\"); err != nil {\n\tif strings.Contains(err.Error(), \"missing Google Chat webhook key\") {\n\t\treturn fmt.Errorf(\"copy the full webhook URL including ?key=...\")\n\t}\n\treturn err\n}","preventionTips":["Copy the complete URL including all query parameters when configuring the webhook","Avoid sharing webhook URLs through channels that trim or redact query strings","Remember the URL embeds secrets — treat it like a credential and store it whole"],"tags":["url","validation","google-chat","missing-parameter"],"backgroundTag":"missing-required-argument","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"}