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
- Free disk space on the Elasticsearch data node (delete old indices, logs, or expand the volume).
- Once free space is above the watermark, remove the block: PUT /<index>/_settings {"index.blocks.read_only_allow_delete": null}.
- Raise or tune cluster routing.disk.watermark settings if the threshold is inappropriate for your environment.
- 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
- Alert when ES disk usage exceeds 85% (before the 95% flood-stage watermark)
- Provision disk headroom for peak indexing loads
- Automatically clear read_only_allow_delete blocks after freeing space
- Monitor SonarQube's ES status metric; treat Red as actionable
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
- Elasticsearch nodes have critically low disk space
- Index [ ] is in read-only mode…
- Node [ ] has critically low disk space: % free ( bytes…
- Failed to retrieve ES attributes. There will be only a…
- At least one Elasticsearch host is required
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)