This error occurs when trying to perform operations on an Elasticsearch index that has been closed. Closed indices cannot be read from or written to until they are reopened. This is a common issue when indices are manually closed for maintenance, or when automated processes close indices based on lifecycle policies.
The "IndexClosedException: closed" error indicates that you're attempting to perform an operation (such as search, index, update, or delete) on an Elasticsearch index that is currently in a closed state. In Elasticsearch, indices can be in one of three states: 1. **Open**: Normal operational state - can be read from and written to 2. **Closed**: Index metadata exists but the index is not accessible for operations 3. **Deleted**: Index has been removed entirely When an index is closed: - Its data remains on disk but is not loaded into memory - No search or indexing operations can be performed - The index consumes minimal resources (only disk space) - It cannot participate in search queries or aggregations Common scenarios that trigger this error: - Manual index closure for maintenance or cost savings - Index lifecycle management (ILM) policies automatically closing old indices - Accidentally closing an index that applications still try to use - Cluster recovery processes leaving indices in closed state
First, verify which indices are closed and understand their current state:
# List all indices with their status
curl -X GET "localhost:9200/_cat/indices?v&h=index,status,health,pri,rep,docs.count,store.size" -u "username:password"
# Check specific index status
curl -X GET "localhost:9200/my-index" -u "username:password"
# Get detailed index information including why it might be closed
curl -X GET "localhost:9200/my-index/_settings?include_defaults=true" -u "username:password"
# Check ILM policy status for the index
curl -X GET "localhost:9200/my-index/_ilm/explain" -u "username:password"
# List only closed indices
curl -X GET "localhost:9200/_cat/indices?v&h=index,status&status=close" -u "username:password"If the index is closed, you'll see "closed" status in the response.
To make the index accessible again, use the open index API:
# Open a single index
curl -X POST "localhost:9200/my-index/_open" -u "username:password"
# Open multiple indices
curl -X POST "localhost:9200/index1,index2,index3/_open" -u "username:password"
# Open indices using wildcard pattern
curl -X POST "localhost:9200/logs-*/_open" -u "username:password"
# Open all closed indices (use with caution)
curl -X POST "localhost:9200/_all/_open" -u "username:password"
# Open with timeout settings (useful for large indices)
curl -X POST "localhost:9200/my-index/_open?timeout=5m" -u "username:password" -H 'Content-Type: application/json' -d'
{
"settings": {
"index.number_of_replicas": 1
}
}
'The open operation:
- Loads index data from disk into memory
- Rebuilds internal data structures
- May take time for large indices
- Returns once the index is ready for operations
After opening an index, monitor its recovery progress:
# Check recovery status
curl -X GET "localhost:9200/_cat/recovery?v&h=index,stage,time,bytes_percent" -u "username:password"
# Verify index is now open and searchable
curl -X GET "localhost:9200/my-index" -u "username:password"
# Test search on the reopened index
curl -X GET "localhost:9200/my-index/_search" -u "username:password" -H 'Content-Type: application/json' -d'
{
"query": {
"match_all": {}
},
"size": 1
}
'
# Check shard allocation status
curl -X GET "localhost:9200/_cat/shards/my-index?v&h=index,shard,prirep,state,unassigned.reason" -u "username:password"
# Monitor cluster health
curl -X GET "localhost:9200/_cluster/health?wait_for_status=yellow&timeout=50s" -u "username:password"Wait for the index to reach "yellow" or "green" health status before using it in production.
If indices are being closed automatically by ILM policies, review and adjust the policies:
# Check current ILM policy
curl -X GET "localhost:9200/_ilm/policy/my-policy" -u "username:password"
# Update ILM policy to prevent unwanted closures
curl -X PUT "localhost:9200/_ilm/policy/my-policy" -u "username:password" -H 'Content-Type: application/json' -d'
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_size": "50gb",
"max_age": "30d"
},
"set_priority": {
"priority": 100
}
}
},
"warm": {
"min_age": "30d",
"actions": {
"set_priority": {
"priority": 50
},
"shrink": {
"number_of_shards": 1
}
}
},
"cold": {
"min_age": "60d",
"actions": {
"set_priority": {
"priority": 0
}
}
},
"delete": {
"min_age": "90d",
"actions": {
"delete": {}
}
}
}
}
}
'
# Remove close action from policy if not needed
# Or adjust min_age to keep indices open longer
# Check which indices are affected by ILM
curl -X GET "localhost:9200/_ilm/explain" -u "username:password"
# Manually move index to different phase
curl -X POST "localhost:9200/_ilm/move/my-index" -u "username:password" -H 'Content-Type: application/json' -d'
{
"current_phase": "hot",
"next_phase": "warm"
}
'Consider whether you need indices to be closed at all. For frequently accessed data, keep indices open.
Add error handling in your application to gracefully deal with closed indices:
// Example: Check index status before operations
const { Client } = require('@elastic/elasticsearch');
const client = new Client({ node: 'http://localhost:9200' });
async function safeSearch(indexName, query) {
try {
const response = await client.search({
index: indexName,
body: query
});
return response;
} catch (error) {
if (error.meta?.body?.error?.type === 'index_closed_exception') {
console.log('Index ' + indexName + ' is closed. Attempting to open...');
try {
// Try to open the index
await client.indices.open({ index: indexName });
console.log('Index ' + indexName + ' opened successfully.');
// Wait a moment for index to become ready
await new Promise(resolve => setTimeout(resolve, 1000));
// Retry the search
const retryResponse = await client.search({
index: indexName,
body: query
});
return retryResponse;
} catch (openError) {
console.error('Failed to open index ' + indexName + ':', openError.message);
throw new Error('Index is closed and could not be opened: ' + openError.message);
}
}
throw error;
}
}
// Example: Bulk operations with closed index handling
async function safeBulkWithClosedIndexHandling(operations) {
const response = await client.bulk({
body: operations,
refresh: true
});
if (response.errors) {
const closedIndices = new Set();
// Check for closed index errors
response.items.forEach(item => {
if (item.index?.error?.type === 'index_closed_exception') {
const indexName = item.index.error.index;
closedIndices.add(indexName);
}
});
// Open closed indices and retry
for (const indexName of closedIndices) {
console.log('Opening closed index: ' + indexName);
try {
await client.indices.open({ index: indexName });
console.log('Successfully opened index: ' + indexName);
} catch (error) {
console.error('Failed to open index ' + indexName + ':', error.message);
}
}
// Retry failed operations if indices were opened
if (closedIndices.size > 0) {
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait for indices to be ready
return await client.bulk({
body: operations,
refresh: true
});
}
}
return response;
}Implement monitoring to detect when indices become closed:
# Elasticsearch monitoring queries
# Check for closed indices (run periodically)
curl -X GET "localhost:9200/_cat/indices?h=index,status&status=close" -u "username:password"
# Set up alert using Elasticsearch alerting or external monitoring
# Example: Check every 5 minutes, alert if critical indices are closed
# Kibana alert example (if using Kibana):
# 1. Create index pattern: "metricbeat-*" or your monitoring indices
# 2. Create threshold alert:
# - Condition: count() > 0
# - Filter: event.dataset: "elasticsearch.index" AND index.status: "close"
# - For indices: "production-*"
# Alternative: Use Elasticsearch Watcher
curl -X PUT "localhost:9200/_watcher/watch/closed_index_alert" -u "username:password" -H 'Content-Type: application/json' -d'
{
"trigger": {
"schedule": {
"interval": "5m"
}
},
"input": {
"search": {
"request": {
"indices": [".monitoring-es-*"],
"body": {
"query": {
"bool": {
"must": [
{
"term": {
"type": "indices"
}
},
{
"term": {
"index_stats.primaries.status": "close"
}
},
{
"wildcard": {
"index_stats.index": "production-*"
}
}
]
}
}
}
}
}
},
"condition": {
"compare": {
"ctx.payload.hits.total": {
"gt": 0
}
}
},
"actions": {
"send_email": {
"email": {
"to": ["[email protected]"],
"subject": "Alert: Production indices closed",
"body": "{{ctx.payload.hits.total}} production indices are closed: {{#ctx.payload.hits.hits}}{{_source.index_stats.index}} {{/ctx.payload.hits.hits}}"
}
}
}
}
'Regular monitoring helps catch issues before they affect applications.
## Advanced Index State Management
### Understanding Index States
Elasticsearch indices have several states that affect operations:
1. Open: Fully operational
2. Closed: Metadata preserved, data on disk but not in memory
3. Read-only: Can be searched but not written to
4. Blocked: Specific operations blocked (write, read, metadata)
### Performance Implications
- Opening a large index can take significant time and resources
- Closed indices don't consume heap memory but still use disk space
- Consider using frozen indices for archival data instead of closing
### Cluster Restart Behavior
When an Elasticsearch cluster restarts:
- Previously open indices remain open
- Previously closed indices remain closed
- Indices recover in priority order (index.priority setting)
### Index Priority
Set index priority to control recovery order:
curl -X PUT "localhost:9200/my-index/_settings" -u "username:password" -H 'Content-Type: application/json' -d'
{
"index.priority": 10
}
'Higher priority indices recover first.
### Shard Allocation Filtering
Prevent indices from being allocated to specific nodes:
# Close indices on nodes you plan to maintain
curl -X PUT "localhost:9200/_cluster/settings" -u "username:password" -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster.routing.allocation.exclude._name": "node-to-maintain"
}
}
'
# Then close indices on that node
curl -X POST "localhost:9200/my-index/_close" -u "username:password"### Snapshot and Restore with Closed Indices
- Closed indices can be included in snapshots
- Restoring a closed index keeps it closed
- Consider this for backup strategies
### Security Considerations
- Use index privileges to control who can open/close indices
- Audit index state changes in security logs
- Implement approval workflows for production index closures
QueryShardException: No mapping found for [field] in order to sort on
How to fix "QueryShardException: No mapping found for field in order to sort on" in Elasticsearch
IndexNotFoundException: no such index [index_name]
How to fix "IndexNotFoundException: no such index [index_name]" in Elasticsearch
DocumentMissingException: [index][type][id]: document missing
DocumentMissingException: Document missing
ParsingException: Unknown key for a START_OBJECT in [query]
How to fix "ParsingException: Unknown key for a START_OBJECT in [query]" in Elasticsearch
AggregationExecutionException: Aggregation [agg_name] does not support sampling
How to fix "AggregationExecutionException: Aggregation [agg_name] does not support sampling" in Elasticsearch