{"record":{"id":"a9eb18b77826bf72","repo":"SonarSource/sonarqube","slug":"failed-to-send-quality-gate-change-email-notificat","errorCode":null,"errorMessage":"Failed to send quality gate change email notification for project {}","messagePattern":"Failed to send quality gate change email notification for project (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/sonar-webserver-core/src/main/java/org/sonar/server/qualitygate/notification/EmailQGChangeEventListener.java","lineNumber":74,"sourceCode":"\n  @Override\n  public void onIssueChanges(QGChangeEvent event, Set<ChangedIssue> changedIssues) {\n    Optional<EvaluatedQualityGate> evaluatedQG = event.getQualityGateSupplier().get();\n    if (evaluatedQG.isEmpty()) {\n      return;\n    }\n\n    Metric.Level newStatus = evaluatedQG.get().getStatus();\n    Optional<Metric.Level> previousStatus = event.getPreviousStatus();\n\n    if (previousStatus.isPresent() && previousStatus.get() == newStatus) {\n      return;\n    }\n\n    try {\n      notifyUsers(event, newStatus, previousStatus.orElse(null));\n    } catch (Exception e) {\n      LOGGER.warn(\"Failed to send quality gate change email notification for project {}\", event.getProject().getKey(), e);\n    }\n  }\n\n  private void notifyUsers(QGChangeEvent event, Metric.Level newStatus, @Nullable Metric.Level previousStatus) {\n    ProjectDto project = event.getProject();\n    BranchDto branch = event.getBranch();\n    EvaluatedQualityGate evaluatedQG = event.getQualityGateSupplier().get().orElseThrow();\n\n    String statusLabel = toStatusLabel(newStatus);\n    boolean isNewAlert = previousStatus == null;\n\n    try (DbSession dbSession = dbClient.openSession(false)) {\n      Map<String, MetricDto> metricsByKey = dbClient.metricDao().selectAll(dbSession).stream()\n        .collect(Collectors.toMap(MetricDto::getKey, Function.identity()));\n\n      String alertText = conditionFormatter.buildAlertText(evaluatedQG, metricKey -> {\n        MetricDto metric = metricsByKey.get(metricKey);\n        return new QualityGateConditionFormatter.MetricInfo(","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-core/src/main/java/org/sonar/server/qualitygate/notification/EmailQGChangeEventListener.java#L56-L92","documentation":"EmailQGChangeEventListener reacts to Quality Gate status change events by sending notification emails. If notifyUsers throws for any reason (SMTP problems, missing project/branch data, template rendering errors), the listener logs this warning with the project key and continues, so notification failure never breaks the compute engine event pipeline.","triggerScenarios":"onIssueChanges -> notifyUsers raising an exception while building or sending the quality-gate-change email for the event's project (e.g. mail server unreachable, no recipients resolved, persistence lookup failure on project/branch DTOs).","commonSituations":"SMTP host misconfigured or down; mail credentials rejected; project deleted between event creation and notification; corrupted branch data; permission/credential lookup failures for subscribed users.","solutions":["Check the logged exception for the root cause (stack trace follows the project key).","Verify email settings (smtp.host, smtp.port, smtp.username/password) in sonar.properties and test connectivity to the SMTP server.","Confirm the project and branch still exist and users' notification subscriptions resolve to valid email addresses.","Re-run the analysis if the notification was critical; the event itself succeeded."],"exampleFix":"// before: unreachable SMTP\nsonar.email.smtp.host=mail.internal.example.com\nsonar.email.smtp.port=25\n// after: corrected reachable SMTP with auth\nsonar.email.smtp.host=smtp.example.com\nsonar.email.smtp.port=587\nsonar.email.smtp.username=sonar@example.com\nsonar.email.smtp.secure.connection=STARTTLS","handlingStrategy":"try-catch","validationCode":"// pre-check SMTP reachability before enabling QG notifications\nconst net = require('net');\nconst s = net.createConnection(587, 'smtp.example.com');\ns.on('connect', () => { console.log('SMTP reachable'); s.end(); });","typeGuard":null,"tryCatchPattern":"try {\n  await mailer.send(qgChangeEmail);\n} catch (e) {\n  logger.warn('Failed to send quality gate change email notification for project ' + projectKey, e);\n  // never rethrow: notifications must not break analysis pipeline\n}","preventionTips":["Validate SMTP host/port/credentials in sonar.properties before production","Ensure notification subscribers have valid email addresses","Avoid deleting projects while analyses/notifications are in flight","Monitor mail server availability"],"tags":["email","notification","quality-gate","smtp"],"backgroundTag":"smtp-delivery-failed","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"}