{"record":{"id":"204b156cd909d5a0","repo":"SonarSource/sonarqube","slug":"webhook-url-is-not-valid","errorCode":null,"errorMessage":"Webhook URL is not valid: ","messagePattern":"Webhook URL is not valid: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-server-common/src/main/java/org/sonar/server/webhook/WebhookCallerImpl.java","lineNumber":76,"sourceCode":"  public WebhookCallerImpl(System2 system, OkHttpClient okHttpClient, WebhookCustomDns webhookCustomDns) {\n    this.system = system;\n    this.webhookCustomDns = webhookCustomDns;\n    this.okHttpClient = newClientWithoutRedirect(okHttpClient, webhookCustomDns);\n  }\n\n  @Override\n  public WebhookDelivery call(Webhook webhook, WebhookPayload payload) {\n    WebhookDelivery.Builder builder = new WebhookDelivery.Builder();\n    long startedAt = system.now();\n    builder\n      .setAt(startedAt)\n      .setPayload(payload)\n      .setWebhook(webhook);\n\n    try {\n      HttpUrl url = HttpUrl.parse(webhook.getUrl());\n      if (url == null) {\n        throw new IllegalArgumentException(\"Webhook URL is not valid: \" + webhook.getUrl());\n      }\n      builder.setEffectiveUrl(HttpUrlHelper.obfuscateCredentials(webhook.getUrl(), url));\n      validateHostIfResolvable(url);\n      Request request = buildHttpRequest(url, webhook, payload);\n      try (Response response = execute(request)) {\n        builder.setHttpStatus(response.code());\n      }\n    } catch (Exception e) {\n      builder.setError(e);\n    }\n\n    return builder\n      .setDurationInMs((int) (system.now() - startedAt))\n      .build();\n  }\n\n  private static Request buildHttpRequest(HttpUrl url, Webhook webhook, WebhookPayload payload) {\n    Request.Builder request = new Request.Builder();","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-server-common/src/main/java/org/sonar/server/webhook/WebhookCallerImpl.java#L58-L94","documentation":"WebhookCallerImpl.call parses the webhook's URL with OkHttp's HttpUrl.parse before sending the HTTP request. If the URL is null (unparseable/malformed), it throws IllegalArgumentException \"Webhook URL is not valid: <url>\" and records the failure in the webhook delivery.","triggerScenarios":"A webhook defined with a URL that OkHttp cannot parse — missing scheme, illegal characters, spaces, or a scheme-less host like 'myserver.example.com/webhook'.","commonSituations":"Admin creating a webhook without 'http://' or 'https://'; copy-paste with leading/trailing spaces or invisible Unicode; typos like 'htp://'.","solutions":["Edit the webhook and set a fully qualified URL starting with http:// or https://.","Trim whitespace and remove illegal characters; re-encode spaces as %20.","Test the URL with curl before saving it; the webhook payload will show the recorded failure.","Validate the URL on webhook creation/update if using the API (api/webhooks/create)."],"exampleFix":"// before\n{\"url\": \"myserver.example.com/hooks/sonarqube\"}\n// after\n{\"url\": \"https://myserver.example.com/hooks/sonarqube\"}","handlingStrategy":"validation","validationCode":"boolean isValidWebhookUrl(String url) {\n  okhttp3.HttpUrl parsed = okhttp3.HttpUrl.parse(url == null ? null : url.trim());\n  return parsed != null && (parsed.isHttps() || parsed.isHttp());\n}","typeGuard":null,"tryCatchPattern":"try { webhookCaller.call(webhook, payload); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"Webhook URL is not valid\")) { log.error(\"Fix webhook URL for {}\", webhook.getName(), e); return; } throw e; }","preventionTips":["Always include http(s):// scheme when defining webhooks","Validate URL on webhook create/update API calls","Trim whitespace and reject non-ASCII in URLs at input time"],"tags":["webhook","url","validation","okhttp"],"backgroundTag":"invalid-url-format","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}