SonarSource/sonarqube · error
Index [ ] is in read-only mode…
Error message
Index [{}] is in read-only mode (index.blocks.read_only_allow_delete=true) What it means
When scanning per-index settings returned by the ES stats API, the task counts indices whose index.blocks.read_only_allow_delete block is true and logs one warning per blocked index. This block is typically set by Elasticsearch's flood-stage watermark to protect the disk, making the index read-only (deletes allowed).
Solutions
- Free disk space above the flood-stage watermark on the ES data node.
- Remove the block per index: PUT /<indexName>/_settings {"index.blocks.read_only_allow_delete": null}.
- Check cluster settings for any manually applied read_only_allow_delete blocks and clear them.
- Confirm via GET /_all/_settings that no blocks remain, then verify ES status turns Green in SonarQube monitoring.
Example fix
# before: index blocked
curl -XGET 'localhost:9001/sonarqube/_settings?pretty' # "read_only_allow_delete": "true"
# after: unblock once disk is freed
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
# verify no blocked indices before indexing curl -s 'localhost:9001/_all/_settings' | jq '[to_entries[] | select(.value.settings.index.blocks.read_only_allow_delete=="true") | .key]'
Try / catch
const blocked = await getBlockedIndices();
if (blocked.length > 0) {
await freeDiskSpaceThenRetry(async () => {
for (const idx of blocked) await es.indices.putSettings({ index: idx, body: { 'index.blocks.read_only_allow_delete': null } });
});
} Prevention
- Keep ES disk usage below the flood-stage watermark (95%) at all times
- After freeing space, explicitly remove the per-index block — it doesn't clear itself
- Check for restored snapshots or copied data dirs carrying block settings
- Include a blocked-index check in routine ES health scripts
When it happens
Trigger: updateAndGetReadOnlyIndicesCount (called from readOnlyIndicesCount path) iterating index states where settings().index().blocks().readOnlyAllowDelete() equals TRUE for a given index name.
Common situations: Disk crossed 95% on the data node causing ES to auto-block indices; indices left blocked after disk cleanup because the block is not removed automatically (pre-7.x behavior / manual setting); restored snapshots carrying block settings.
Related errors
- Elasticsearch indices are in read-only mode, likely due to…
- Elasticsearch nodes have critically low disk space
- Node [ ] has critically low disk space: % free ( bytes…
- At least one Elasticsearch host is required
- Can not resolve host [
AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09).
Data as JSON: /api/errors/08010a96f563fec9.
Report an issue: GitHub.
Appendix: source
Thrown at server/sonar-webserver-monitoring/src/main/java/org/sonar/server/monitoring/ElasticSearchMetricTask.java:136
} catch (Exception e) {
LOG.error("Failed to query ES status", e);
}
}
private long updateAndGetReadOnlyIndicesCount() {
try {
final GetIndicesSettingsResponse settingsResponse = esClient.getSettingsV2(req -> req.index("*"));
final Map<String, IndexState> indices = settingsResponse.settings();
long readOnlyCount = 0;
for (Map.Entry<String, IndexState> entry : indices.entrySet()) {
final String indexName = entry.getKey();
final IndexState indexState = entry.getValue();
if (indexState.settings() != null && indexState.settings().index() != null) {
final var blocks = indexState.settings().index().blocks();
if (blocks != null && Boolean.TRUE.equals(blocks.readOnlyAllowDelete())) {
LOG.warn("Index [{}] is in read-only mode (index.blocks.read_only_allow_delete=true)", indexName);
readOnlyCount++;
}
}
}
// Update metric for observability
serverMonitoringMetrics.setElasticSearchReadOnlyIndicesCount(readOnlyCount);
return readOnlyCount;
} catch (Exception e) {
LOG.error("Failed to check for readonly indices", e);
// Return 0 on error to avoid false positives - let cluster health handle it
return 0;
}
}
private double updateAndGetMaxDiskUsagePercent(@Nullable NodeStatsResponse nodeStatsResponse, double thresholdPercent) {
try {View on GitHub (pinned to 184c821202)