SonarSource/sonarqube · warning

Failed to retrieve ES attributes. There will be only a…

Error message

Failed to retrieve ES attributes. There will be only a single "state" attribute.

What it means

This is a warning logged by the ES (Elasticsearch) state section of the System Info page when collecting Elasticsearch node attributes fails. The section normally publishes attributes like 'State' (Green/Yellow/Red) plus node details into the System Info protobuf; on failure it degrades gracefully and only emits a single 'State' attribute derived from the exception message.

Solutions

  1. Check Elasticsearch is running and reachable at the configured sonar.search host/port (curl the ES node's HTTP endpoint).
  2. Inspect the logged exception and its cause; if it is an ElasticsearchException the State attribute will carry its message — fix the reported cluster issue (e.g. red health, missing indices).
  3. Verify sonar.search.* configuration matches the embedded/external ES instance.
  4. Restart the node after disk/network issues so ES health returns to Green/Yellow.

Example fix

// before (typical failure: ES not reachable)
sonar.search.host=127.0.0.1
sonar.search.port=9001
// after: confirm ES is up and port matches
# curl http://127.0.0.1:9001/_cluster/health
sonar.search.host=127.0.0.1
sonar.search.port=9001
Defensive patterns

Strategy: try-catch

Validate before calling

// check ES reachability before hitting the System Info state section
const res = await fetch('http://es-host:9001/_cluster/health');
if (!res.ok) throw new Error('ES unreachable: ' + res.status);

Type guard

function isEsHealth(v) {
  return v != null && typeof v === 'object' && typeof v.status === 'string';
}

Try / catch

try {
  const health = await esClient.cluster.health();
} catch (e) {
  logger.warn('Failed to retrieve ES attributes', e); // degrade to limited state
}

Prevention

When it happens

Trigger: Calling toProtobuf (via the Search State web service section) when the ES client throws while fetching health/node info — e.g. node down, connection failure, or an ElasticsearchException returned by the cluster.

Common situations: Elasticsearch stopped or restarting during web server startup; wrong ES host/port settings (sonar.search.host/port); ES8 mixed-case HealthStatus handling paths; cluster health timeouts.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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

Appendix: source

Thrown at server/sonar-webserver-core/src/main/java/org/sonar/server/platform/monitoring/EsStateSection.java:58

  public EsStateSection(EsClient esClient) {
    this.esClient = esClient;
  }

  private HealthStatus getStateAsEnum() {
    return esClient.clusterHealthV2(req -> req).status();
  }

  @Override
  public ProtobufSystemInfo.Section toProtobuf() {
    ProtobufSystemInfo.Section.Builder protobuf = ProtobufSystemInfo.Section.newBuilder();
    protobuf.setName("Search State");
    try {
      // ES8 HealthStatus enum is mixed-case (Green/Yellow/Red); webapp expects upper-case
      // for the System Info "State" field (see StatusIndicator.tsx ICON_MAP).
      setAttribute(protobuf, "State", getStateAsEnum().name().toUpperCase(Locale.ENGLISH));
      completeNodeAttributes(protobuf);
    } catch (Exception es) {
      LoggerFactory.getLogger(EsStateSection.class).warn("Failed to retrieve ES attributes. There will be only a single \"state\" attribute.", es);
      Throwable cause = es.getCause();
      setAttribute(protobuf, "State",
        cause instanceof ElasticsearchException ? cause.getMessage() : es.getMessage());
    }
    return protobuf.build();
  }

  private void completeNodeAttributes(ProtobufSystemInfo.Section.Builder protobuf) {
    NodeStatsResponse nodesStatsResponse = esClient.nodesStats();

    if (!nodesStatsResponse.getNodeStats().isEmpty()) {
      toProtobuf(nodesStatsResponse.getNodeStats().get(0), protobuf);
    }
  }

  public static void toProtobuf(NodeStats stats, ProtobufSystemInfo.Section.Builder protobuf) {
    setAttribute(protobuf, "CPU Usage (%)", stats.getCpuUsage());
    setAttribute(protobuf, "Disk Available", humanReadableByteCountSI(stats.getDiskAvailableBytes()));

View on GitHub (pinned to 184c821202)