This error occurs when attempting to create or access an Elasticsearch index with uppercase letters in its name. Elasticsearch enforces a strict lowercase naming convention for index names to ensure consistency and avoid filesystem conflicts.
The InvalidIndexNameException with "must be lowercase" message is Elasticsearch's validation error that prevents index creation with uppercase letters. This restriction exists because Elasticsearch needs to handle index names consistently across case-sensitive and case-insensitive filesystems. Since index metadata is stored on disk, allowing mixed case could lead to conflicts on case-insensitive filesystems like NTFS or macOS HFS+. Elasticsearch enforces strict index naming conventions to maintain compatibility across different operating systems and file systems. When you attempt to create an index like "MyIndex" or "TEST-Index", Elasticsearch immediately rejects it with this exception before any data is written. This validation happens at the REST API layer before the index creation reaches the cluster state management. The error message typically shows the invalid index name in brackets, making it easy to identify which name needs correction.
First, locate the exact index name causing the error. The error message shows it in brackets:
InvalidIndexNameException: Invalid index name [MyIndex], must be lowercaseCheck where this index name is defined in your code, configuration, or API request. Common locations:
- Application code making index creation calls
- Configuration files (elasticsearch.yml, logstash.conf)
- API requests in scripts or tools
- Index template patterns
Update the index name to use only lowercase letters. Here's how to fix common scenarios:
Direct API call:
# Before (causes error)
curl -X PUT "localhost:9200/MyIndex"
# After (works correctly)
curl -X PUT "localhost:9200/myindex"In application code (Node.js example):
// Before
const indexName = "UserData";
await client.indices.create({ index: indexName });
// After
const indexName = "userdata";
// Or dynamically convert
const indexName = "UserData".toLowerCase();
await client.indices.create({ index: indexName });In Python:
# Before
index_name = "MyIndex"
# After
index_name = "myindex"
# Or
index_name = "MyIndex".lower()Ensure your index name follows all Elasticsearch naming rules:
Valid characters:
- Lowercase letters (a-z)
- Numbers (0-9)
- Hyphens (-)
- Underscores (_)
Invalid patterns to avoid:
# Invalid: uppercase letters
MyIndex, TEST, User-Data
# Invalid: starts with hyphen, underscore, or plus
-myindex, _myindex, +myindex
# Invalid: contains spaces
my index, user data
# Invalid: contains special characters
my*index, my#index, my?index, my/index
# Invalid: contains backslash, comma, angle brackets, pipe, quotes
my\index, my,index, my<index, my|index, "myindex"
# Valid examples
myindex, user-data, logs-2024, app_metricsLength limit:
Index names must not exceed 255 bytes (usually 255 characters for ASCII).
If you use index templates, ensure patterns generate lowercase names:
Index template with proper naming:
PUT _index_template/logs-template
{
"index_patterns": ["logs-*"],
"template": {
"settings": {
"number_of_shards": 1
},
"mappings": {
"properties": {
"@timestamp": { "type": "date" }
}
}
}
}Logstash configuration:
output {
elasticsearch {
hosts => ["localhost:9200"]
# Use lowercase with date pattern
index => "logs-%{+yyyy.MM.dd}"
# Avoid: index => "Logs-%{+yyyy.MM.dd}"
}
}Filebeat configuration:
output.elasticsearch:
hosts: ["localhost:9200"]
# Use lowercase
index: "filebeat-%{[agent.version]}-%{+yyyy.MM.dd}"Add index name validation before calling Elasticsearch to prevent runtime errors:
JavaScript/TypeScript:
function validateIndexName(name: string): string {
// Convert to lowercase
let validName = name.toLowerCase();
// Replace invalid characters with hyphens
validName = validName.replace(/[^a-z0-9_-]/g, '-');
// Remove leading special characters
validName = validName.replace(/^[_+-]+/, '');
// Ensure not just dots
if (/^.+$/.test(validName)) {
throw new Error('Index name cannot consist only of dots');
}
// Check length
if (validName.length > 255) {
validName = validName.substring(0, 255);
}
return validName;
}
// Usage
const userInput = "MyIndex";
const safeName = validateIndexName(userInput);
await client.indices.create({ index: safeName });Python:
import re
def validate_index_name(name: str) -> str:
# Convert to lowercase
valid_name = name.lower()
# Replace invalid characters
valid_name = re.sub(r'[^a-z0-9_-]', '-', valid_name)
# Remove leading special characters
valid_name = re.sub(r'^[_+-]+', '', valid_name)
# Check if only dots
if re.match(r'^.+$', valid_name):
raise ValueError("Index name cannot consist only of dots")
# Truncate if too long
if len(valid_name.encode('utf-8')) > 255:
valid_name = valid_name[:255]
return valid_name
# Usage
user_input = "MyIndex"
safe_name = validate_index_name(user_input)
es.indices.create(index=safe_name)If you have aliases, application references, or documentation using the old uppercase name, update them:
Create an alias for backward compatibility (if needed):
# Create the lowercase index
PUT /myindex
# Create an alias with a similar name (must also be lowercase)
POST /_aliases
{
"actions": [
{
"add": {
"index": "myindex",
"alias": "my-index-alias"
}
}
]
}Update application configuration:
- Search your codebase for hardcoded index names
- Update environment variables
- Modify configuration files
- Update API documentation
- Inform team members of the naming change
Search for references:
# In a Git repository
git grep -i "MyIndex"
# Update all references to use lowercase## Why Lowercase is Mandatory
Elasticsearch enforced this restriction starting in version 2.x due to filesystem compatibility issues. On case-insensitive filesystems (Windows NTFS, macOS HFS+), "MyIndex" and "myindex" would refer to the same file, creating potential data corruption and conflicts. By enforcing lowercase, Elasticsearch ensures consistent behavior across all operating systems.
## Complete Index Naming Rules
From the Elasticsearch documentation:
1. Must be lowercase
2. Cannot start with -, _, or +
3. Cannot be . or ..
4. Cannot contain /, \, *, ?, ", <, >, |, (space), ,, or #
5. Indices prior to 7.0 could contain a colon (:), but deprecated since 7.0
6. Must be 255 bytes or less (not characters, bytes in UTF-8)
7. Names starting with . are reserved for internal Elasticsearch indices
## Programmatic Index Name Generation
For applications generating index names dynamically:
Date-based indices (common for logs):
const date = new Date();
const indexName = `logs-${date.getFullYear()}.${(date.getMonth() + 1).toString().padStart(2, '0')}.${date.getDate().toString().padStart(2, '0')}`;
// Result: logs-2024.01.15User-based indices:
def generate_user_index(username: str) -> str:
# Sanitize and convert to lowercase
sanitized = username.lower().replace(' ', '-')
return f"users-{sanitized}"## Migrating from Uppercase Index Names
If you have an existing uppercase index (created in very old Elasticsearch versions or through other means), you cannot rename it directly. Use reindexing:
# Reindex from old to new lowercase index
POST _reindex
{
"source": {
"index": "old_mixed_case_index"
},
"dest": {
"index": "new_lowercase_index"
}
}
# Verify data copied
GET /new_lowercase_index/_count
# Delete old index after verification
DELETE /old_mixed_case_index## Index Aliases as Abstraction
Use aliases to decouple your application from physical index names:
# Create indexes with timestamped names
PUT /logs-2024-01-15
PUT /logs-2024-01-16
# Point a consistent alias to the current index
POST /_aliases
{
"actions": [
{ "add": { "index": "logs-2024-01-16", "alias": "logs-current" } }
]
}
# Application always writes to "logs-current"
# No code changes needed when rotating indices## Configuration Best Practices
In elasticsearch.yml (cluster-level settings):
Elasticsearch doesn't have a setting to override lowercase enforcement. This is hardcoded validation for data integrity.
In client libraries:
Most official clients (elasticsearch-js, elasticsearch-py) don't perform client-side validation. The server returns the error. Consider wrapping client calls with validation functions as shown in the main steps.
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
IllegalStateException: There are no ingest nodes in this cluster, unable to forward request to an ingest node
How to fix "There are no ingest nodes in this cluster" 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