apache/skywalking · error · IllegalArgumentException
PagerDuty hook: [{hookName}] events-api-url must be an absol
Error message
PagerDuty hook: [{hookName}] events-api-url must be an absolute http(s) URL, but was: [{url}]. What it means
IllegalArgumentException thrown by RulesReader.validateEventsApiUrl when the events-api-url parses as a URI but is not an absolute http(s) URL — either uri.getHost() is null (relative/authority-less URI) or the scheme is not http/https (e.g. ftp, mailto). PagerDuty notifications are sent as HTTP POSTs, so the client needs an absolute URL with a host.
Source
Thrown at oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReader.java:407
* Rejects a malformed `events-api-url` while the config is being read, so a typo fails startup (or the dynamic
* config update) instead of surfacing later as a per-alarm {@link URI#create} failure inside the hook callback,
* where every alarm would be dropped with only an error log.
*
* @param url the configured endpoint
* @param hookName the hook the endpoint belongs to, for the error message
*/
private void validateEventsApiUrl(String url, String hookName) {
final URI uri;
try {
uri = new URI(url);
} catch (URISyntaxException e) {
throw new IllegalArgumentException(
"PagerDuty hook: [" + hookName + "] events-api-url is malformed: [" + url + "].", e);
}
final String scheme = uri.getScheme();
if (uri.getHost() == null
|| !("https".equalsIgnoreCase(scheme) || "http".equalsIgnoreCase(scheme))) {
throw new IllegalArgumentException(
"PagerDuty hook: [" + hookName + "] events-api-url must be an absolute http(s) URL, but was: ["
+ url + "].");
}
// The integration key travels in the request body, so a non-TLS endpoint puts a credential on the wire.
if (!"https".equalsIgnoreCase(scheme)) {
log.warn(
"PagerDuty hook [{}] is configured with a non-https events-api-url [{}]. "
+ "The integration key is sent in the request body and will not be encrypted.",
hookName, url
);
}
}
/**
* Read PagerDuty hook config into {@link PagerDutySettings}
*/
@SuppressWarnings("unchecked")
private void readPagerDutyConfig(Map hooks, Rules rules) {View on GitHub (pinned to 102af09b4a)
Solutions
- Prefix the URL with the scheme: `https://events.pagerduty.com/v2/enqueue`.
- Note the follow-up warn: an http:// URL is accepted but the integration key travels unencrypted in the request body — prefer https, or use an http URL only against a TLS-terminating internal proxy.
- If using templating, ensure the template renders scheme+host+path together, not just the host.
- Restart OAP / re-push the config after fixing; validation is fail-fast at config read.
Example fix
# before
hooks:
pagerduty:
pagerduty-hook:
events-api-url: events.pagerduty.com/v2/enqueue # no scheme, host==null
# after
hooks:
pagerduty:
pagerduty-hook:
events-api-url: https://events.pagerduty.com/v2/enqueue Defensive patterns
Strategy: validation
Validate before calling
// Accept only absolute http(s) with host, mirroring RulesReader:
URI u = URI.create(url);
boolean ok = u.getHost() != null
&& ("https".equalsIgnoreCase(u.getScheme()) || "http".equalsIgnoreCase(u.getScheme())); Prevention
- Always include the scheme; prefer https because the PagerDuty integration key is sent in the body.
- Add a CI lint that every configured webhook/PagerDuty URL matches ^https://[^/]+/.* .
- Beware templated values that inject only a hostname.
When it happens
Trigger: A PagerDuty hook URL like `events.pagerduty.com/v2/enqueue` (no scheme, so URI treats the whole thing as a path and host is null), `localhost:8080/x` without `http://` (parsed as scheme `localhost`), or a non-http scheme such as `ftp://...`. Only `http` and `https` (case-insensitive) with a non-null host pass.
Common situations: Omitting the scheme when editing config by hand; an env-var template that injects only the host part; using a service-short-name URL in Kubernetes (`http://pagerduty-proxy.svc` is fine but `pagerduty-proxy.svc` alone fails); switching from a fully-qualified URL to an internal short name and dropping `http://`.
Related errors
- PagerDuty hook: [{hookName}] events-api-url is malformed: [{
- Expression: {expression} is not a SINGLE_VALUE result expres
- The metrics in expression: {expression} must have the same s
- expression can't be empty
- tag() reads LogData tags but the input type is {inputTypeNam
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/542fd85884ccaa62.
Report an issue: GitHub.