SonarSource/sonarqube · error · NotFoundException

Email configuration with id

Error message

Email configuration with id %s not found

What it means

EmailConfigurationService supports exactly one email configuration, stored under a fixed internal property key UNIQUE_EMAIL_CONFIGURATION_ID. throwIfNotUniqueConfigurationId throws NotFoundException for any id other than that fixed value. Since the ID is fixed by the platform, any caller-supplied id that differs is reported as 'not found'.

Solutions

  1. Call the list/get endpoint without an id first to discover the actual supported configuration id and use exactly that
  2. Delete with the same id returned by getConfiguration
  3. If migrating, recreate settings under the supported id rather than reusing legacy ids

Example fix

// before
deleteConfiguration("my-smtp-1")
// after
EmailConfiguration cfg = getConfiguration(UNIQUE_EMAIL_CONFIGURATION_ID);
deleteConfiguration(cfg.getId()); // the single supported id
Defensive patterns

Strategy: validation

Validate before calling

// discover the supported id before read/delete
List<EmailConfiguration> configs = client.getEmailConfigurations();
if (configs.isEmpty()) throw new IllegalStateException("no email configuration exists");
String id = configs.get(0).getId(); // use this id, never a custom one

Type guard

boolean isKnownEmailConfigId(String id, Set<String> knownIds) {
  return id != null && knownIds.contains(id);
}

Try / catch

try {
  service.deleteConfiguration(id);
} catch (NotFoundException e) {
  log.warn("Email configuration id '{}' not found; listing valid ids", id);
  // fall back to listing and re-resolving the id
}

Prevention

When it happens

Trigger: GET/DELETE email configuration endpoints with an arbitrary id (e.g. copied from an old doc, a UUID, or 'default') instead of the single supported id; stale client code that cached a different id.

Common situations: API consumers assume multiple email configs exist and pass their own ids; integrations migrated from other products that allowed multiple SMTP configurations; typo in the reserved id.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/6598c586b4177907. Report an issue: GitHub.

Appendix: source

Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/email/config/EmailConfigurationService.java:165

      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_PORT),
      EmailConfigurationSecurityProtocol.valueOf(getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_SECURE_CONNECTION)),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_FROM),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_FROM_NAME),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_PREFIX),
      EmailConfigurationAuthMethod.valueOf(getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_AUTH_METHOD)),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_USERNAME),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_PASSWORD),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_OAUTH_HOST),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_OAUTH_CLIENTID),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_OAUTH_CLIENTSECRET),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_OAUTH_TENANT),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_OAUTH_SCOPE),
      getStringInternalPropertyOrEmpty(dbSession, EMAIL_CONFIG_SMTP_OAUTH_GRANT));
  }

  private static void throwIfNotUniqueConfigurationId(String id) {
    if (!UNIQUE_EMAIL_CONFIGURATION_ID.equals(id)) {
      throw new NotFoundException(format("Email configuration with id %s not found", id));
    }
  }

  private String getStringInternalPropertyOrEmpty(DbSession dbSession, String property) {
    return dbClient.internalPropertiesDao().selectByKey(dbSession, property).orElse("");
  }

  public Optional<EmailConfiguration> findConfigurations() {
    try (DbSession dbSession = dbClient.openSession(false)) {
      if (configurationExists(dbSession)) {
        return Optional.of(getConfiguration(UNIQUE_EMAIL_CONFIGURATION_ID, dbSession));
      }
      return Optional.empty();
    }
  }

  public EmailConfiguration updateConfiguration(UpdateEmailConfigurationRequest updateRequest) {
    try (DbSession dbSession = dbClient.openSession(true)) {

View on GitHub (pinned to 184c821202)