Skip to content

Commit 43939aa

Browse files
committed
Improve error messages on bad [format] and [null_value] params for date mapper (#61932)
Currently, if an incorrectly formatted date is passed as a null_value for a date field mapper configuration, you get a vague error: Failed to parse mapping [_doc]: cannot parse empty date Similarly, if you pass an incorrect format, you get the error: Failed to parse mapping [_doc]: Invalid format [...] This commit improves both these errors by including the mapper name and parameter that are misconfigured. Fixes #61712
1 parent 59bf7a9 commit 43939aa

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -240,21 +240,36 @@ public boolean isFormatterSet() {
240240
return format.explicit();
241241
}
242242

243-
protected DateFieldType setupFieldType(BuilderContext context) {
243+
private DateFormatter buildFormatter(BuilderContext context) {
244244
String pattern = this.format.value();
245-
DateFormatter formatter;
246-
if (Joda.isJodaPattern(context.indexCreatedVersion(), pattern)) {
247-
formatter = Joda.forPattern(pattern).withLocale(locale);
248-
} else {
249-
formatter = DateFormatter.forPattern(pattern).withLocale(locale);
245+
try {
246+
if (Joda.isJodaPattern(context.indexCreatedVersion(), pattern)) {
247+
return Joda.forPattern(pattern).withLocale(locale);
248+
} else {
249+
return DateFormatter.forPattern(pattern).withLocale(locale);
250+
}
251+
} catch (IllegalArgumentException e) {
252+
throw new IllegalArgumentException("Error parsing [format] on field [" + name() + "]: " + e.getMessage(), e);
253+
}
254+
}
255+
256+
private Long parseNullValue(DateFormatter formatter) {
257+
if (nullValue == null) {
258+
return null;
259+
}
260+
try {
261+
return formatter.parseMillis(nullValue);
262+
}
263+
catch (Exception e) {
264+
throw new MapperParsingException("Error parsing [null_value] on field [" + name() + "]: " + e.getMessage(), e);
250265
}
251-
return new DateFieldType(buildFullName(context), indexed, hasDocValues, formatter, resolution, meta);
252266
}
253267

254268
@Override
255269
public DateFieldMapper build(BuilderContext context) {
256-
DateFieldType ft = setupFieldType(context);
257-
Long nullTimestamp = nullValue == null ? null : ft.dateTimeFormatter.parseMillis(nullValue);
270+
DateFieldType ft = new DateFieldType(buildFullName(context), indexed, hasDocValues, buildFormatter(context), resolution, meta);
271+
272+
Long nullTimestamp = parseNullValue(ft.dateTimeFormatter);
258273
return new DateFieldMapper(name, fieldType, ft, ignoreMalformed(context), nullTimestamp, nullValue,
259274
multiFieldsBuilder.build(this, context), copyTo);
260275
}

server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.util.Set;
4646

4747
import static org.hamcrest.Matchers.containsString;
48+
import static org.hamcrest.Matchers.equalTo;
4849
import static org.hamcrest.Matchers.notNullValue;
4950

5051
public class DateFieldMapperTests extends FieldMapperTestCase<DateFieldMapper.Builder> {
@@ -332,7 +333,7 @@ public void testNullConfigValuesFail() throws MapperParsingException, IOExceptio
332333
.endObject().endObject());
333334

334335
Exception e = expectThrows(MapperParsingException.class, () -> parser.parse("type", new CompressedXContent(mapping)));
335-
assertEquals("[format] must not have a [null] value", e.getMessage());
336+
assertThat(e.getMessage(), containsString("[format] must not have a [null] value"));
336337
}
337338

338339
public void testEmptyName() throws IOException {
@@ -347,6 +348,24 @@ public void testEmptyName() throws IOException {
347348
assertThat(e.getMessage(), containsString("name cannot be empty string"));
348349
}
349350

351+
public void testBadNullValue() throws IOException {
352+
353+
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
354+
.startObject("type")
355+
.startObject("properties")
356+
.startObject("field")
357+
.field("type", "date")
358+
.field("format", "")
359+
.endObject()
360+
.endObject()
361+
.endObject().endObject());
362+
363+
Exception e = expectThrows(Exception.class, () -> parser.parse("type", new CompressedXContent(mapping)));
364+
365+
assertThat(e.getMessage(),
366+
equalTo("Error parsing [format] on field [field]: No date pattern provided"));
367+
}
368+
350369
public void testTimeZoneParsing() throws Exception {
351370
final String timeZonePattern = "yyyy-MM-dd" + randomFrom("XXX", "[XXX]", "'['XXX']'");
352371

@@ -435,7 +454,8 @@ public void testIllegalFormatField() throws Exception {
435454

436455
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
437456
() -> parser.parse("type", new CompressedXContent(mapping)));
438-
assertEquals("Invalid format: [[test_format]]: Unknown pattern letter: t", e.getMessage());
457+
assertThat(e.getMessage(), containsString("Invalid format: [[test_format]]: Unknown pattern letter: t"));
458+
assertThat(e.getMessage(), containsString("Error parsing [format] on field [field]: Invalid"));
439459
}
440460

441461
public void testMeta() throws Exception {

0 commit comments

Comments
 (0)