elastic/elasticsearch · error · IllegalArgumentException
${clazz.getSimpleName()} value passed as String
Error message
${clazz.getSimpleName()} value passed as String What it means
Thrown by AbstractXContentParser.checkCoerceString() when coerce is false and the parser encounters a VALUE_STRING token for a field that expects a Number type. The coercion policy (DEFAULT_NUMBER_COERCE_POLICY=true by default) normally allows strings like "42" to be parsed as numbers, but when a caller explicitly disables coercion (coerce=false), any string representation of a number is rejected.
Source
Thrown at libs/x-content/src/main/java/org/elasticsearch/xcontent/support/AbstractXContentParser.java:48
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
public abstract class AbstractXContentParser implements XContentParser {
// Currently this is not a setting that can be changed and is a policy
// that relates to how parsing of things like "boost" are done across
// the whole of Elasticsearch (eg if String "1.0" is a valid float).
// The idea behind keeping it as a constant is that we can track
// references to this policy decision throughout the codebase and find
// and change any code that needs to apply an alternative policy.
public static final boolean DEFAULT_NUMBER_COERCE_POLICY = true;
public static void checkCoerceString(boolean coerce, Class<? extends Number> clazz) {
if (coerce == false) {
// Need to throw type IllegalArgumentException as current catch logic in
// NumberFieldMapper.parseCreateField relies on this for "malformed" value detection
throw new IllegalArgumentException(clazz.getSimpleName() + " value passed as String");
}
}
private final NamedXContentRegistry xContentRegistry;
private final DeprecationHandler deprecationHandler;
private final RestApiVersion restApiVersion;
public AbstractXContentParser(
NamedXContentRegistry xContentRegistry,
DeprecationHandler deprecationHandler,
RestApiVersion restApiVersion
) {
this.xContentRegistry = xContentRegistry;
this.deprecationHandler = deprecationHandler;
this.restApiVersion = restApiVersion;
}
public AbstractXContentParser(NamedXContentRegistry xContentRegistry, DeprecationHandler deprecationHandler) {View on GitHub (pinned to db6a809a66)
Solutions
- Send the numeric value as a JSON number (no quotes) instead of a string.
- If string-to-number coercion is acceptable, enable coerce in the field mapping.
- Update the client serializer to emit numbers without quotes for numeric fields.
- Validate the JSON payload to ensure numeric fields contain bare numbers, not strings.
Example fix
// before — number sent as string with coerce disabled
PUT /my-index/_doc/1
{ "price": "99.99" }
// after — number sent as JSON number
PUT /my-index/_doc/1
{ "price": 99.99 } Defensive patterns
Strategy: validation
Validate before calling
// Before indexing, verify numeric fields are not passed as strings
public static void validateNumericFields(Map<String, Object> doc, Map<String, Class<?>> numericFields) {
for (Map.Entry<String, Class<?>> entry : numericFields.entrySet()) {
Object val = doc.get(entry.getKey());
if (val instanceof String && Number.class.isAssignableFrom(entry.getValue())) {
throw new IllegalArgumentException(
entry.getKey() + " must be a number, not a string (coerce is disabled)"
);
}
}
} Try / catch
try {
parser.shortValue(false); // or intValue/longValue with coerce=false
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("value passed as String")) {
// Re-read the value and handle the coercion error
throw new BadRequestException("Numeric field received a string value: " + e.getMessage());
}
throw e;
} Prevention
- Send numeric values as JSON numbers (unquoted), not as strings, for numeric fields.
- If coerce is disabled in the mapping, strictly validate value types client-side.
- Use typed serialization (e.g., Jackson with proper numeric types) to avoid quoting numbers.
When it happens
Trigger: A field mapper with 'coerce: false' in the mapping receiving a JSON string value for a numeric field (e.g., sending "42" as a string for an integer field with coercion disabled). Calling shortValue(false), intValue(false), or longValue(false) on the parser when the current token is VALUE_STRING.
Common situations: Index settings or field mappings with coerce disabled to enforce strict numeric types. Client library serializing numbers as strings (e.g., JavaScript BigInt or BigDecimal as strings). Sending numeric query parameters as quoted strings.
Related errors
- ${fullVal} cannot be converted to ${clazz.getSimpleName()} w
- [{}] {} doesn't support values of type: {}
- Value [${text}] is out of range for a short
- Value [${text}] is out of range for an integer
- Numeric value length [${length}] exceeds the maximum of [${M
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/be8dd3a11d702a23.
Report an issue: GitHub.