How to fix IndexClosedException: closed in Elasticsearch

ElasticsearchINTERMEDIATEMEDIUMUpdated Dec 22, 2025· 125 views

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.

Quick fix

Fixes IndexClosedException: closed

# 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"
  1. Check index status using the indices API
  2. Open the closed index using the open API
  3. Monitor index recovery and verify it's operational
  4. Review and adjust ILM policies if applicable
elasticsearch — error
# 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"
IndexClosedException: closed

What this error means

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

Typical symptoms

  • Search queries return "IndexClosedException: closed" error
  • Indexing operations fail with "closed" status messages
  • Bulk API requests show failures for operations targeting closed indices
  • Application logs show repeated failures when accessing specific indices
  • Dashboard tools show indices with "closed" state in cluster health reports
  • GET index API returns {"status": "closed"} instead of index settings
  • Index appears in _cat/indices output with "close" status

Common causes

  1. Index was manually closed using the close index API
  2. Index lifecycle management (ILM) policy moved index to cold/delete phase
  3. Automated script or tool closed indices to save resources
  4. Cluster recovery or restart left indices in closed state
  5. Disk space pressure triggered automatic index closure
  6. Index was closed during maintenance and never reopened
  7. Application trying to use time-based indices that have rolled over and closed

How to fix "IndexClosedException: closed"

1Check index status using the indices API

First, verify which indices are closed and understand their current state:

bash
# 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.

2Open the closed index using the open API

To make the index accessible again, use the open index API:

bash
# 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

3Monitor index recovery and verify it's operational

After opening an index, monitor its recovery progress:

bash
# 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.

4Review and adjust ILM policies if applicable

If indices are being closed automatically by ILM policies, review and adjust the policies:

bash
# 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.

5Implement defensive code to handle closed indices

Add error handling in your application to gracefully deal with closed indices:

javascript
// 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;
}
6Set up monitoring and alerts for index state changes

Implement monitoring to detect when indices become closed:

bash
# 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": ["admin@example.com"],
        "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 notes

## 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:

bash
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:

bash
# 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

Frequently asked questions

What does "IndexClosedException: closed" mean?
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.
How do I fix "IndexClosedException: closed"?
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.
What causes "IndexClosedException: closed"?
Index was manually closed using the close index API Index lifecycle management (ILM) policy moved index to cold/delete phase Automated script or tool closed indices to save resources
Is the "IndexClosedException: closed" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading