SonarSource/sonarqube · error

Elasticsearch indices are in read-only mode, likely due to…

Error message

Elasticsearch indices are in read-only mode, likely due to disk space issues

What it means

The Elasticsearch monitoring task sets the ES health metric. When at least one ES index carries the read_only_allow_delete block (usually applied automatically by ES flood-stage watermark when disk usage exceeds 95%), the task logs this warning and marks the Elasticsearch status Red, signaling that writes (indexing) are failing or will fail.

Solutions

  1. Free disk space on the Elasticsearch data node (delete old indices, logs, or expand the volume).
  2. Once free space is above the watermark, remove the block: PUT /<index>/_settings {"index.blocks.read_only_allow_delete": null}.
  3. Raise or tune cluster routing.disk.watermark settings if the threshold is inappropriate for your environment.
  4. Restart SonarQube's ES node after cleanup and confirm status returns to Green.

Example fix

# before: index blocked
curl -XGET localhost:9001/_all/_settings | grep read_only_allow_delete
# after: free disk space, then unblock
curl -XPUT 'localhost:9001/sonarqube/_settings' -H 'Content-Type: application/json' -d '{"index.blocks.read_only_allow_delete": null}'
Defensive patterns

Strategy: retry

Validate before calling

# before running analyses, check for read-only blocks and disk
while read idx; do echo "$idx is blocked"; done < <(curl -s localhost:9001/_all/_settings | jq -r 'to_entries[] | select(.value.settings.index.blocks.read_only_allow_delete=="true") | .key')
curl -s localhost:9001/_nodes/stats/fs | jq '.nodes[] | {name:.name, free:.fs.total.free_in_bytes, total:.fs.total.total_in_bytes}'

Try / catch

// poll until the block clears before retrying indexing
for (let i = 0; i < 5; i++) {
  const blocks = await checkReadOnlyBlocks();
  if (blocks === 0) return retryIndexing();
  await sleep(60_000);
}

Prevention

When it happens

Trigger: updateElasticSearchHealthStatus (from run) finding updateAndGetReadOnlyIndicesCount() > 0, i.e. any index reporting index.blocks.read_only_allow_delete=true in node/cluster stats.

Common situations: Disk on the ES data node filled past the 95% flood-stage watermark; undersized disk for large analysis histories; Docker/Kubernetes volume limits reached; forgotten watermark settings after expanding storage.

Related errors


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

Appendix: source

Thrown at server/sonar-webserver-monitoring/src/main/java/org/sonar/server/monitoring/ElasticSearchMetricTask.java:76

      nodeStatsResponse = esClient.nodesStats();
    } catch (Exception e) {
      LOG.error("Failed to query ES node stats", e);
    }
    updateElasticSearchHealthStatus(nodeStatsResponse);
    updateFileSystemMetrics(nodeStatsResponse);
  }

  private void updateElasticSearchHealthStatus(@Nullable final NodeStatsResponse nodeStatsResponse) {
    try {
      HealthStatus esStatus = esClient.clusterHealthV2(req -> req).status();

      long readOnlyIndicesCount = updateAndGetReadOnlyIndicesCount();
      final double thresholdPercent = config.getDouble(DISK_SPACE_THRESHOLD_PROPERTY)
        .orElse(DEFAULT_DISK_SPACE_THRESHOLD_PERCENT);
      double maxDiskUsagePercent = updateAndGetMaxDiskUsagePercent(nodeStatsResponse, thresholdPercent);

      if (readOnlyIndicesCount > 0) {
        LOG.warn("Elasticsearch indices are in read-only mode, likely due to disk space issues");
        serverMonitoringMetrics.setElasticSearchStatusToRed();
        return;
      }

      final double freePercent = 100.0 - maxDiskUsagePercent;

      if (freePercent < thresholdPercent) {
        LOG.warn("Elasticsearch nodes have critically low disk space");
        serverMonitoringMetrics.setElasticSearchStatusToRed();
        return;
      }

      // Fall back to cluster health status
      if (esStatus == null) {
        serverMonitoringMetrics.setElasticSearchStatusToRed();
      } else {
        switch (esStatus) {
          case Green, Yellow:

View on GitHub (pinned to 184c821202)