Logstash Error: '_jsonparsefailure' — Cause, Fix, and Troubleshooting Guide
Fix Logstash '_jsonparsefailure' from the json filter: guard non-JSON input, fix multiline framing, and use skip_on_invalid_json.
- #logstash
- #logging
- #troubleshooting
- #errors
Stuck on this Logstash error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
What this error means
The Logstash json filter takes a field, parses it as a JSON document, and merges the result into the event. When the field it was told to parse is not valid JSON, the filter cannot fail the event outright — it adds the tag _jsonparsefailure and passes the event through untouched. In /var/log/logstash/logstash-plain.log the underlying parse error is logged like this:
[WARN ][logstash.filters.json ][main] Error parsing json {:source=>"message", :raw=>"{\"level\":\"info\", \"msg\":\"started\"", :exception=>#<LogStash::Json::ParserError: Unexpected end-of-input: expected close marker for Object>}
This is the filter-side failure, and it is distinct from a Jackson JSON parse error raised at the elasticsearch output (that is a different problem, covered separately). Here, the json filter is telling you that the specific field named in :source — usually message — did not contain a complete, well-formed JSON object. The :raw value in the log is the exact text it choked on, which is the single most useful clue: in the example above the object is truncated, missing its closing }.
Where records stall
- Events arrive in Elasticsearch carrying a
_jsonparsefailuretag but with the JSON left unparsed insidemessage. logstash-plain.logshowsError parsing jsonwith aLogStash::Json::ParserErrorand a:rawsnippet.- The exception text hints at the shape of the problem:
Unexpected end-of-input(truncated),Unexpected character(not JSON), orUnrecognized token. - Some events parse fine and others fail — typically the failing ones are large or multiline records that were split.
- Downstream dashboards show fields missing on a subset of events because the merge never happened.
Following a record through the pipeline
Start by isolating the exact bytes that failed. The :raw value in the log is the failing input; copy it and validate it with a strict parser:
# Pull recent failures and their raw payloads
grep 'logstash.filters.json' /var/log/logstash/logstash-plain.log | tail -20
# Validate a captured payload with a strict JSON parser
echo '{"level":"info", "msg":"started"' | jq .
# parse error: Unexpected end of input — confirms truncation
Route tagged events to a file so you can inspect real failures without touching Elasticsearch. Add a temporary debug output keyed on the tag:
output {
if "_jsonparsefailure" in [tags] {
file { path => "/var/lib/logstash/json-failures.log" }
}
}
Then look at whether the failures are fragments of a larger record. If the raw values are consistently missing their opening { or closing }, the payload is being split before Logstash — the framing is the problem, not the parser:
# Are failures short fragments rather than whole documents?
awk '{ print length, $0 }' /var/lib/logstash/json-failures.log | sort -n | head
For reference, a strict json filter that only runs on plausibly-JSON input looks like this:
filter {
if [message] =~ /^\s*\{/ {
json {
source => "message"
skip_on_invalid_json => true
}
}
}
Pipeline causes
- The field is not JSON at all — plain text, a syslog line, or a key=value log was routed into a
jsonfilter. - Truncated JSON from split multiline logs — a pretty-printed or stack-trace-bearing JSON record spanning several lines was ingested as several separate events, so each event holds a fragment.
- Invalid JSON dialect — single quotes instead of double quotes, trailing commas, unquoted keys, or
NaN/Infinityvalues that strict JSON rejects. - Concatenated objects — two JSON documents on one line (
{...}{...}) with no array wrapper; strict parsers stop after the first. - Wrong
sourcefield — the filter points at a field that holds only part of the payload, or a field that is already a parsed object. - A codec already parsed it — an input
codec => jsonplus a redundantjsonfilter double-parses, and the second pass sees a non-string.
Remediation
Guard the filter with a conditional so only messages that actually look like JSON are parsed. This alone eliminates _jsonparsefailure on mixed log streams:
filter {
if [message] =~ /^\s*\{/ {
json { source => "message" }
}
}
Set skip_on_invalid_json => true so a non-JSON field is skipped quietly instead of tagging the event and logging a warning for every line:
filter {
json {
source => "message"
skip_on_invalid_json => true
}
}
Fix multiline framing upstream when the failures are truncated documents. Each event must be one complete JSON record. If Filebeat ships the logs, stitch the lines there so Logstash receives whole documents:
# filebeat.yml — reassemble a JSON object that starts with "{"
filebeat.inputs:
- type: filestream
id: app-json
paths:
- /var/log/app/*.json.log
parsers:
- multiline:
type: pattern
pattern: '^\{'
negate: true
match: after
Route the survivors aside rather than letting malformed data pollute your index. Tag-based branching keeps clean data flowing while you triage the rest:
output {
if "_jsonparsefailure" in [tags] {
file { path => "/var/lib/logstash/json-failures-%{+YYYY.MM.dd}.log" }
} else {
elasticsearch { hosts => ["https://es.internal:9200"] index => "app-%{+YYYY.MM.dd}" }
}
}
Keeping ingestion stable
:rawis your evidence. Always read the raw snippet before changing config — it tells you whether you have non-JSON, truncation, or a dialect issue, which need different fixes.- Do not double-parse. If an input
codec => jsonalready decoded the payload, a secondjsonfilter onmessagewill fail or misbehave; remove one of them. - Multiline belongs in one place. Do the stitching in Filebeat or with a multiline codec on a
fileinput — never both, or you will re-split what you just joined. skip_on_invalid_jsonhides the signal. It stops the tag and the warning, which is convenient, but you lose visibility into genuinely broken producers — keep a sampled failure output while you stabilize.- Trailing commas and single quotes are not JSON. If an upstream service emits them, fix the producer; Logstash’s parser is deliberately strict.
Related pipeline errors
- Logstash Jackson JSON parse error at the output
- Logstash ‘_grokparsefailure’ tag
- Logstash ‘_dateparsefailure’ tag
Fixed it? Get 500 Logstash & 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.
Did this fix your issue?
Trending errors this week
The error guides other engineers are actually reading right now.
- 1mount: wrong fs type, bad option, bad superblock
- 2Docker 'failed to set up container networking': Fix the Bridge and IP Pool
- 3Docker 'failed to create shim task': How to Fix the containerd Runtime Error
- 4modprobe: FATAL: Module not found
- 5mount: wrong fs type, bad option, bad superblock
- 6Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
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.