SonarSource/sonarqube · warning
onChange() call failed on listener %s for events %s
Error message
onChange() call failed on listener %s for events %s
What it means
broadcastChangeEventToListener wraps each individual listener.onIssueChanges() call in try/catch(Exception). If a listener throws a regular Exception, it is logged as a warning naming the listener class and the event, so one broken listener does not affect others.
Source
Thrown at server/sonar-webserver-api/src/main/java/org/sonar/server/qualitygate/changeevent/QGChangeEventListenersImpl.java:111
branchQgChangeEvents.forEach(changeEvent -> broadcastChangeEventToListeners(changedIssues, changeEvent));
}
private static ImmutableSet<ChangedIssue> toChangedIssues(Collection<DefaultIssue> defaultIssues, boolean fromAlm) {
return defaultIssues.stream()
.map(defaultIssue -> new ChangedIssueImpl(defaultIssue, fromAlm))
.collect(toImmutableSet());
}
private void broadcastChangeEventToListeners(Set<ChangedIssue> changedIssues, QGChangeEvent changeEvent) {
listeners.forEach(listener -> broadcastChangeEventToListener(changedIssues, changeEvent, listener));
}
private static void broadcastChangeEventToListener(Set<ChangedIssue> changedIssues, QGChangeEvent changeEvent, QGChangeEventListener listener) {
try {
LOG.trace("calling onChange() on listener {} for events {}...", listener.getClass().getName(), changeEvent);
listener.onIssueChanges(changeEvent, changedIssues);
} catch (Exception e) {
LOG.warn(format("onChange() call failed on listener %s for events %s", listener.getClass().getName(), changeEvent), e);
}
}
}
View on GitHub (pinned to 184c821202)
Solutions
- Identify the listener class named in the log message and inspect its stack trace.
- Fix the bug in the custom listener (or report it to the plugin maintainer).
- Disable/uninstall the failing listener plugin if it cannot be fixed.
- Verify downstream effects (e.g. notifications/webhooks) and re-run the affected computation if events were dropped.
Example fix
// inside a custom listener
// before
public void onIssueChanges(QGChangeEvent event, Set<ChangedIssue> issues) { db.sessions()... }
// after
public void onIssueChanges(QGChangeEvent event, Set<ChangedIssue> issues) {
try (DbSession s = db.openSession(false)) { ... }
} Defensive patterns
Strategy: try-catch
Try / catch
// in your custom listener implementation
@Override
public void onIssueChanges(QGChangeEvent e, Set<ChangedIssue> issues) {
try { doWork(e, issues); }
catch (Exception ex) { LOG.warn("onChange failed", ex); }
} Prevention
- Never let exceptions escape listener.onIssueChanges implementations
- Guard DB sessions and external calls inside listeners
- Log and isolate per-event failures so one event does not abort the batch
When it happens
Trigger: Any registered QGChangeEventListener whose onIssueChanges() implementation throws (DB failure, NPE, REST call failure inside the listener) during broadcastOnAnyChange or branch broadcast.
Common situations: Third-party webhooks/notification listener plugins failing on malformed events; a listener hitting a database outage while processing quality-gate changes.
Related errors
- Broadcasting to listeners failed for %s events
- Unsupported value '%s' of Measure.Level can not be converted
- Unsupported value '%s' of Measure.Level can not be converted
- There is no metric with key=%s
- Github configuration is not complete. Please check your conf
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/79ca58bd21f5b9f1.
Report an issue: GitHub.