Andrew Mercer
on this page

jq only tells you whether the JSON is well-formed. To catch unknown parameters, bad field types or invalid settings, you need Elasticsearch itself to parse the JSON. A disposable single-node container does that.

1. Syntax check

jq empty test.json && echo "valid JSON"

2. Start a throwaway node

docker run --rm -d --name es-lint \
  -p 127.0.0.1:19200:9200 \
  -e discovery.type=single-node \
  -e xpack.security.enabled=false \
  -e ES_JAVA_OPTS="-Xms512m -Xmx512m" \
  docker.elastic.co/elasticsearch/elasticsearch:9.1.5

until curl -s localhost:19200 >/dev/null; do sleep 2; done

Match the image tag to the version you're targeting. Map only one host port: passing -p 19200:9200 and -p 9200:9200 together also tries to bind host port 9200, which fails if anything else is listening there.

3. Apply the JSON

test.json is the request body, for example { "mappings": { ... }, "settings": { ... } }:

curl -s -X PUT localhost:19200/test-mapping \
  -H 'Content-Type: application/json' -d @test.json | jq

A good result is "acknowledged": true. A bad one returns an error.root_cause[].reason that names the offending field.

For a whole index template, PUT _index_template/test followed by POST _index_template/_simulate_index/<name> validates it and shows the merged output.

4. Clean up

docker stop es-lint   # --rm removes the container