{"record":{"id":"e0330b1ab81b6bb7","repo":"bytebase/bytebase","slug":"failed-to-construct-webhook-post-request-to-s-e0330b","errorCode":null,"errorMessage":"failed to construct webhook POST request to %s","messagePattern":"failed to construct webhook POST request to (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/webhook/discord/discord.go","lineNumber":101,"sourceCode":"\t}\n\tif context.ActorName != \"\" {\n\t\tembed.Author = &WebhookEmbedAuthor{\n\t\t\tName: fmt.Sprintf(\"%s (%s)\", context.ActorName, context.ActorEmail),\n\t\t}\n\t}\n\tembedList = append(embedList, embed)\n\n\tpost := Webhook{\n\t\tEmbedList: embedList,\n\t}\n\tbody, err := json.Marshal(post)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to marshal webhook POST request to %s\", context.URL)\n\t}\n\treq, err := http.NewRequest(\"POST\",\n\t\tcontext.URL, bytes.NewBuffer(body))\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to construct webhook POST request to %s\", context.URL)\n\t}\n\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\tclient := &http.Client{\n\t\tTimeout: webhook.Timeout,\n\t}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to POST webhook to %s\", context.URL)\n\t}\n\n\tb, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to read POST webhook response from %s\", context.URL)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/webhook/discord/discord.go#L83-L119","documentation":"This error wraps an http.NewRequest failure while constructing the POST request to the configured Discord webhook URL. It fires when the request cannot be built at all — most commonly a URL that fails http.NewRequest's parsing (control characters) or an unsupported scheme.","triggerScenarios":"http.NewRequest(\"POST\", context.URL, ...) returns an error, typically because the stored webhook URL is malformed (whitespace/control characters) rather than merely unparseable scheme.","commonSituations":"An IM setting URL pasted with trailing newline/space, quotes, or corrupted by a bad migration; a misconfigured base URL in deployment config.","solutions":["Check the configured webhook URL for stray whitespace, newlines, or quotes and correct it in IM settings.","Validate the URL with url.Parse before saving the webhook configuration.","Re-copy the Discord webhook URL from Discord's integration UI."],"exampleFix":"// before\nif err != nil {\n  return errors.Wrapf(err, \"failed to construct webhook POST request to %s\", context.URL)\n}\n// after (caller-side guard before configuring)\nu, err := url.Parse(strings.TrimSpace(webhookURL))\nif err != nil || u.Scheme != \"https\" || !strings.Contains(u.Host, \"discord.com\") {\n  return fmt.Errorf(\"invalid discord webhook url %q\", webhookURL)\n}","handlingStrategy":"validation","validationCode":"u, err := url.Parse(strings.TrimSpace(webhookURL))\nif err != nil || u.Scheme != \"https\" || u.Host == \"\" {\n  return fmt.Errorf(\"invalid discord webhook url\")\n}\nif !strings.HasPrefix(u.Path, \"/api/webhooks/\") {\n  return fmt.Errorf(\"not a discord webhook url\")\n}","typeGuard":"func isDiscordWebhookURL(raw string) bool {\n  u, err := url.Parse(strings.TrimSpace(raw))\n  return err == nil && u.Scheme == \"https\" && strings.HasPrefix(u.Host, \"discord.com\") && strings.HasPrefix(u.Path, \"/api/webhooks/\")\n}","tryCatchPattern":"if err := discord.Post(ctx, whCtx); err != nil {\n  if strings.Contains(err.Error(), \"construct\") {\n    return fmt.Errorf(\"webhook URL invalid, re-configure: %w\", err)\n  }\n  return err\n}","preventionTips":["Trim whitespace when storing webhook URLs from user input.","Validate URL format/scheme at IM settings save time.","Copy the URL directly from Discord's integration UI."],"tags":["webhook","discord","http","url"],"backgroundTag":"invalid-url","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}