Logstash Error Guide: 'Limit of total fields [1000] has been exceeded' — Stop the Mapping Explosion
Fix Logstash 'Limit of total fields [1000] has been exceeded': find the high-cardinality keys, control dynamic mapping, and prune fields before they explode.
- #logstash
- #logging
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
Elasticsearch caps the number of fields an index mapping may contain (default 1000). When Logstash keeps sending events with new, previously-unseen field names, dynamic mapping adds each one — until the index hits the ceiling and the elasticsearch output starts rejecting documents:
[WARN ][logstash.outputs.elasticsearch] Could not index event to Elasticsearch.
{:status=>400, :action=>["index", {:_index=>"app-logs-2026.07.11"}, {...}],
:response=>{"index"=>{"error"=>{
"type"=>"illegal_argument_exception",
"reason"=>"Limit of total fields [1000] in index [app-logs-2026.07.11] has been exceeded"}}}}
This is a mapping explosion: it’s rarely a legitimate schema of 1000 fields and almost always a handful of high-cardinality keys being promoted to fields — per-request IDs used as JSON keys, dynamic labels, or an unparsed blob exploded by a json/kv filter. Every event after the limit is a non-retryable 400 and is dropped (or sent to the DLQ).
Symptoms
Limit of total fields [N] in index [...] has been exceededwithillegal_argument_exceptionand:status=>400.- New documents stop appearing in Kibana while old ones remain; the failure is index-wide, not per-source.
- The index’s mapping is huge and full of one-off field names (UUIDs, timestamps, or IDs as keys).
- Errors began after adding a
json/kvfilter, ingesting a new app, or a code change that emits dynamic keys. - Cluster state grows and master nodes get slower as the mapping bloats.
Common Root Causes
- High-cardinality keys promoted to fields — JSON objects keyed by user/request/trace ID (
{"req_9f3a...": {...}}), so every request mints a new field. kvfilter on free-form text — key=value parsing of arbitrary logs invents a field per distinct key.jsonfilter on a deeply dynamic payload — expanding a nested object whose keys are data, not schema.- Metrics/labels as fields — Prometheus-style label sets or per-tenant attributes flattened into distinct mappings.
- No dynamic-mapping policy — the index lets Elasticsearch map every new field it sees, with no
dynamic: falseguardrail. - Limit raised instead of fixed — someone bumped
total_fields.limitto 5000, delaying the same crash.
How to diagnose
Confirm the error and which index is affected:
grep 'Limit of total fields' /var/log/logstash/logstash-plain.log | tail -5
Count the fields actually in the mapping — a number near the limit confirms explosion:
curl -s 'http://es:9200/app-logs-2026.07.11/_mapping?pretty' | grep -c '"type"'
Look at the field names to spot the pattern — long lists of UUID/ID-like keys are the tell:
curl -s 'http://es:9200/app-logs-2026.07.11/_mapping?pretty' \
| grep -oE '"[a-f0-9-]{16,}"' | head
Check whether the current limit was already raised:
curl -s 'http://es:9200/app-logs-2026.07.11/_settings?pretty' | grep total_fields
Fixes
1. Stop promoting high-cardinality keys — keep the dynamic blob as data, not schema. Nest it under one field and disable mapping of its contents in a composable template:
PUT _index_template/app-logs
{
"index_patterns": ["app-logs-*"],
"template": {
"settings": { "index.mapping.total_fields.limit": 1000 },
"mappings": {
"dynamic": true,
"properties": {
"raw_payload": { "type": "object", "enabled": false }
}
}
}
}
enabled: false stores the object but indexes none of its keys, so it can’t add fields.
2. Move the dynamic data into one non-exploding field in the Logstash filter, instead of letting json/kv spray keys:
filter {
# Instead of json { source => "msg" } which explodes dynamic keys,
# keep the blob intact under a disabled field:
mutate { rename => { "msg" => "raw_payload" } }
}
3. Constrain the kv filter so it only extracts known keys rather than every token:
filter {
kv {
source => "message"
include_keys => ["user", "status", "path", "duration"] # allow-list only
remove_char_key => " "
}
}
4. Prune the noise before output — drop dynamic fields you don’t query:
filter {
prune {
whitelist_names => ["^@timestamp$", "^message$", "^host", "^user$",
"^status$", "^path$", "^duration$", "^raw_payload$"]
}
}
5. Add a dynamic-mapping guardrail so unknown strings map to keyword (cheap) and objects don’t recurse into new fields:
"dynamic_templates": [
{ "strings_as_keywords": {
"match_mapping_type": "string",
"mapping": { "type": "keyword", "ignore_above": 256 } } }
]
Then roll over to a new index so the template takes effect (mappings are immutable in place).
What to watch out for
- Raising
index.mapping.total_fields.limitis a stopgap, not a fix — it postpones the same crash and bloats cluster state; fix the cardinality instead. - The limit is per index, so a rollover to a fresh index temporarily clears the error but the explosion resumes unless the root cause is fixed.
enabled: falsemakes a field’s contents unsearchable/unaggregatable — good for opaque blobs, wrong for data you actually query, so choose per field.kvandjsonon free-form text are the usual culprits; always allow-list keys or keep the payload intact under one disabled object.- Fixing the template only affects newly created indices; the bloated current index needs a rollover, and historical data a reindex, to shrink.
- Enable the DLQ so events rejected during the explosion are captured rather than silently dropped while you remediate.
Related
- Logstash Error Guide: mapper_parsing_exception
- Logstash Error Guide: retrying failed action … 429
- Logstash Error Guide: dead letter queue is full
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.