elastic / elasticsearch

Free and Open Source, Distributed, RESTful Search Engine
https://www.elastic.co/products/elasticsearch
Other
1.09k stars 24.83k forks source link

DateTimeException should be 4xx #112190

Closed craigtaverner closed 1 month ago

craigtaverner commented 2 months ago

An invalid MonthOfYear value (0) caused all shard to fail, RemoteTransportExeception and a 500 http status code. We feel this should rather be a code in the 4xx range, since it is an error in the search query.

Failed to execute phase [query], all shards failed; shardFailures {[PLWFic-nQKaByz8rQ1Labw][vendor-hotel][0]: org.elasticsearch.transport.RemoteTransportException: [es-es-search-78c47d7586-8bzj7][100.64.110.2:9300][indices:data/read/search[phase/query]]
Caused by: java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12): 0
    at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:319)
    at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:718)
    at java.base/java.time.LocalDate.of(LocalDate.java:273)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.time.DateTime.query(DateTime.java:50)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.time.DateFormatters.from(DateFormatters.java:2385)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.time.DateFormatters.from(DateFormatters.java:2368)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.time.JavaDateMathParser.parseDateTime(JavaDateMathParser.java:210)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.time.JavaDateMathParser.parse(JavaDateMathParser.java:63)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.mapper.DateFieldMapper$DateFieldType.parseToLong(DateFieldMapper.java:677)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.mapper.DateFieldMapper$DateFieldType.isFieldWithinQuery(DateFieldMapper.java:748)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.mapper.DateFieldMapper$DateFieldType.isFieldWithinQuery(DateFieldMapper.java:723)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.RangeQueryBuilder.getRelation(RangeQueryBuilder.java:474)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.RangeQueryBuilder.doSearchRewrite(RangeQueryBuilder.java:493)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.AbstractQueryBuilder.doRewrite(AbstractQueryBuilder.java:309)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.AbstractQueryBuilder.rewrite(AbstractQueryBuilder.java:280)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.BoolQueryBuilder.rewriteClauses(BoolQueryBuilder.java:400)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.BoolQueryBuilder.doRewrite(BoolQueryBuilder.java:356)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.AbstractQueryBuilder.rewrite(AbstractQueryBuilder.java:280)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.BoolQueryBuilder.rewriteClauses(BoolQueryBuilder.java:400)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.BoolQueryBuilder.doRewrite(BoolQueryBuilder.java:355)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.AbstractQueryBuilder.rewrite(AbstractQueryBuilder.java:280)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.builder.SubSearchSourceBuilder.rewrite(SubSearchSourceBuilder.java:89)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.builder.SubSearchSourceBuilder.rewrite(SubSearchSourceBuilder.java:37)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.Rewriteable.rewrite(Rewriteable.java:57)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.Rewriteable.rewrite(Rewriteable.java:40)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.Rewriteable.rewrite(Rewriteable.java:125)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.builder.SearchSourceBuilder.rewrite(SearchSourceBuilder.java:1176)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.builder.SearchSourceBuilder.rewrite(SearchSourceBuilder.java:93)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.Rewriteable.rewrite(Rewriteable.java:57)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.Rewriteable.rewrite(Rewriteable.java:40)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.internal.ShardSearchRequest$RequestRewritable.rewrite(ShardSearchRequest.java:587)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.internal.ShardSearchRequest$RequestRewritable.rewrite(ShardSearchRequest.java:576)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.index.query.Rewriteable.rewrite(Rewriteable.java:57)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.SearchService.createSearchContext(SearchService.java:1147)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.SearchService.createContext(SearchService.java:1076)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.SearchService.executeQueryPhase(SearchService.java:685)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.search.SearchService.lambda$executeQueryPhase$2(SearchService.java:559)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.action.ActionRunnable$3.accept(ActionRunnable.java:78)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.action.ActionRunnable$3.accept(ActionRunnable.java:75)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.action.ActionRunnable$4.doRun(ActionRunnable.java:100)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:26)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.util.concurrent.TimedRunnable.doRun(TimedRunnable.java:33)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:991)
    at org.elasticsearch.server@8.16.0/org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:26)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1570)
elasticsearchmachine commented 2 months ago

Pinging @elastic/es-search (Team:Search)

smalyshev commented 2 months ago

@craigtaverner Could you provide an example of the query/date that leads to this failure?

smalyshev commented 2 months ago

I think something like this should fix it:

--- a/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java
+++ b/server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java
@@ -674,7 +674,11 @@ public final class DateFieldMapper extends FieldMapper {
             LongSupplier now,
             Resolution resolution
         ) {
-            return resolution.convert(dateParser.parse(BytesRefs.toString(value), now, roundUp, zone));
+            try {
+                return resolution.convert(dateParser.parse(BytesRefs.toString(value), now, roundUp, zone));
+            } catch (DateTimeException | ArithmeticException e) {
+                throw new ElasticsearchParseException("failed to parse date field [" + value + "]", e);
+            }
         }

         @Override
craigtaverner commented 1 month ago

@craigtaverner Could you provide an example of the query/date that leads to this failure?

I was not able to see the query in the server logs. This was not a CI test failure, but an issue in a cloud instance. I speculate the user entered an invalid date with an invalid month, eg. "2024-0-1"