elastic/elasticsearch · error · IllegalArgumentException

Required [{fields}]

Error message

Required [{fields}]

What it means

After all fields are consumed, ConstructingObjectParser checks each constructor argument slot; any slot still null for a required (non-optional) constructorArg is collected into a comma-separated list and reported. The message enumerates every missing required argument in declaration order. Optional constructor args (optionalConstructorArg) do not trigger this; only required constructorArg() slots do.

Source

Thrown at libs/x-content/src/main/java/org/elasticsearch/xcontent/ConstructingObjectParser.java:556

            /*
             * The object hasn't been built which ought to mean we're missing some constructor arguments. But they could be optional! We'll
             * check if they are all optional and build the error message at the same time - if we don't start the error message then they
             * were all optional!
             */
            StringBuilder message = null;
            for (int i = 0; i < constructorArgs.length; i++) {
                if (constructorArgs[i] != null) continue;
                ConstructorArgInfo arg = constructorArgInfos.get(parser.getRestApiVersion()).get(i);
                if (false == arg.required) continue;
                if (message == null) {
                    message = new StringBuilder("Required [").append(arg.field);
                } else {
                    message.append(", ").append(arg.field);
                }
            }
            if (message != null) {
                // There were non-optional constructor arguments missing.
                throw new IllegalArgumentException(message.append(']').toString());
            }
            /*
             * If there weren't any constructor arguments declared at all then we won't get an error message but this isn't really a valid
             * use of ConstructingObjectParser. You should be using ObjectParser instead. Since this is more of a programmer error and the
             * parser ought to still work we just assert this.
             */
            assert false == constructorArgInfos.isEmpty()
                : "["
                    + objectParser.getName()
                    + "] must configure at least one constructor "
                    + "argument. If it doesn't have any it should use ObjectParser instead of ConstructingObjectParser. This is a bug "
                    + "in the parser declaration.";
            // All missing constructor arguments were optional. Just build the target and return it.
            buildTarget();
            return targetObject;
        }

        private void buildTarget() {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Add the missing field(s) named in the message to the input object.
  2. If the field is genuinely optional at your call site, declare it with optionalConstructorArg() instead of constructorArg() in the parser definition.
  3. Verify the field name sent matches a registered ParseField (including all deprecated aliases) so the value actually populates the slot.

Example fix

// before: parser requires 'name' and 'type' as constructor args, input omits 'type'
{"name": "foo"}

// after
{"name": "foo", "type": "bar"}
Defensive patterns

Strategy: validation

Validate before calling

// before calling apply(), confirm all required constructor-arg fields are present
Set<String> required = Set.of("name", "type"); // fields declared via constructorArg()
Map<String,Object> body = parseToMap(parserClone);
if (!body.keySet().containsAll(required)) {
    throw new IllegalArgumentException("missing required fields: " + Sets.difference(required, body.keySet()));
}

Try / catch

try {
    Value v = cop.apply(parser, ctx);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Required [")) {
        // collect missing fields from message and ask the client to supply them
    }
}

Prevention

When it happens

Trigger: Input object omits one or more fields declared with constructorArg() (required). Sending a subset of the required fields, or sending them under deprecated/alternate names not registered, leaves the slot null.

Common situations: Client sends a partial request body missing mandatory fields. Field renamed between versions and the old name no longer maps. Test fixtures that don't include all required fields.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/43f957e20e7ccfd8. Report an issue: GitHub.