Skip to content

bug: strict schema validation rejects unknown fields on all ES API commands #170

@Kiryous

Description

@Kiryous

Summary

All 292 auto-generated ES API schemas apply Zod strict mode, which rejects any field not explicitly defined in the schema. This means plugin-specific fields, fields from newer ES versions, and any undocumented parameters are rejected client-side even though Elasticsearch would accept them.

This is the same class of bug as #155 (bulk _source stripping). PR #159 fixed it for 3 NDJSON APIs (bulk, msearch, msearch_template) by extending their schemas with z.any() array fields, but the remaining 289 schemas are still strict.

Environment

  • CLI: 0.1.0-alpha.1 (commit 1b91960)
  • OS: Darwin 25.4.0 arm64

Repro

echo '{"index":"test","query":{"match_all":{}},"_custom_plugin_field":"value"}' \
  | elastic es search --dry-run

Actual result

Error: input validation failed:
✖ Unrecognized key: "_custom_plugin_field"

Expected result

The CLI should pass unknown fields through to Elasticsearch and let the server decide whether they are valid.

Root cause

factory.ts line ~680 applies .strict() to every z.object() input schema unless the schema already has a .passthrough() catchall:

const validationSchema = (
  config.input instanceof z.ZodObject &&
  (config.input.def as unknown as { catchall?: { type: string } }).catchall?.type !== 'unknown'
)
  ? config.input.strict()
  : config.input

Since all codegen'd schemas are plain z.object() (none use .passthrough()), every one gets strict mode:

Passthrough: 0 / 292
Strict:    292 / 292

Impact

  • ES plugins that add custom request fields (e.g. security, APM, custom ingest) are unusable from the CLI
  • Users running a newer ES version than the CLI's schema generation will hit rejections for new fields
  • Breaks forward-compatibility — the CLI becomes the bottleneck for API evolution

Possible fix

Either the codegen should emit .passthrough() on all request schemas, or the factory should stop applying .strict() by default. The CLI's job is to route parameters correctly, not to be a stricter validator than ES itself.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions