org.elasticsearch.ElasticsearchException Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :server
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexFormatTooNewException;
import org.apache.lucene.index.IndexFormatTooOldException;
import org.apache.lucene.store.AlreadyClosedException;
import org.apache.lucene.store.LockObtainFailedException;
import org.elasticsearch.action.support.replication.ReplicationOperation;
import org.elasticsearch.cluster.action.shard.ShardStateAction;
import org.elasticsearch.common.io.stream.NotSerializableExceptionWrapper;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.logging.LoggerMessageFormat;
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.elasticsearch.core.CheckedFunction;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.Tuple;
import org.elasticsearch.health.node.action.HealthNodeNotDiscoveredException;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.mapper.DocumentParsingException;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.indices.AutoscalingMissedIndicesUpdateException;
import org.elasticsearch.indices.FailureIndexNotSupportedException;
import org.elasticsearch.indices.recovery.RecoveryCommitTooNewException;
import org.elasticsearch.ingest.GraphStructureException;
import org.elasticsearch.persistent.NotPersistentTaskNodeException;
import org.elasticsearch.persistent.PersistentTaskNodeNotAssignedException;
import org.elasticsearch.rest.ApiNotAvailableException;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchException;
import org.elasticsearch.search.TooManyScrollContextsException;
import org.elasticsearch.search.aggregations.AggregationExecutionException;
import org.elasticsearch.search.aggregations.MultiBucketConsumerService;
import org.elasticsearch.search.aggregations.UnsupportedAggregationOnDownsampledIndex;
import org.elasticsearch.search.query.SearchTimeoutException;
import org.elasticsearch.transport.TcpTransport;
import org.elasticsearch.xcontent.ParseField;
import org.elasticsearch.xcontent.ToXContentFragment;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParser;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystemException;
import java.nio.file.FileSystemLoopException;
import java.nio.file.NoSuchFileException;
import java.nio.file.NotDirectoryException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableMap;
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_UUID_NA_VALUE;
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureFieldName;
/**
* A base class for all elasticsearch exceptions.
*/
public class ElasticsearchException extends RuntimeException implements ToXContentFragment, Writeable {
private static final TransportVersion UNKNOWN_VERSION_ADDED = TransportVersions.ZERO;
/**
* Passed in the {@link Params} of {@link #generateThrowableXContent(XContentBuilder, Params, Throwable)}
* to control if the {@code caused_by} element should render. Unlike most parameters to {@code toXContent} methods this parameter is
* internal only and not available as a URL parameter.
*/
public static final String REST_EXCEPTION_SKIP_CAUSE = "rest.exception.cause.skip";
/**
* Passed in the {@link Params} of {@link #generateThrowableXContent(XContentBuilder, Params, Throwable)}
* to control if the {@code stack_trace} element should render. Unlike most parameters to {@code toXContent} methods this parameter is
* internal only and not available as a URL parameter. Use the {@code error_trace} parameter instead.
*/
public static final String REST_EXCEPTION_SKIP_STACK_TRACE = "rest.exception.stacktrace.skip";
public static final boolean REST_EXCEPTION_SKIP_STACK_TRACE_DEFAULT = true;
private static final boolean REST_EXCEPTION_SKIP_CAUSE_DEFAULT = false;
private static final String INDEX_METADATA_KEY = "es.index";
private static final String INDEX_METADATA_KEY_UUID = "es.index_uuid";
private static final String SHARD_METADATA_KEY = "es.shard";
private static final String RESOURCE_METADATA_TYPE_KEY = "es.resource.type";
private static final String RESOURCE_METADATA_ID_KEY = "es.resource.id";
private static final String TYPE = "type";
private static final String REASON = "reason";
private static final String CAUSED_BY = "caused_by";
private static final ParseField SUPPRESSED = new ParseField("suppressed");
public static final String STACK_TRACE = "stack_trace";
private static final String HEADER = "header";
private static final String ERROR = "error";
private static final String ROOT_CAUSE = "root_cause";
private static final Map> ID_TO_SUPPLIER;
private static final Map, ElasticsearchExceptionHandle> CLASS_TO_ELASTICSEARCH_EXCEPTION_HANDLE;
private final Map> metadata = new HashMap<>();
private final Map> headers = new HashMap<>();
/**
* Construct a ElasticsearchException
with the specified cause exception.
*/
public ElasticsearchException(Throwable cause) {
super(cause);
}
/**
* Construct a ElasticsearchException
with the specified detail message.
*
* The message can be parameterized using {}
as placeholders for the given
* arguments
*
* @param msg the detail message
* @param args the arguments for the message
*/
public ElasticsearchException(String msg, Object... args) {
super(LoggerMessageFormat.format(msg, args));
}
/**
* Construct a ElasticsearchException
with the specified detail message
* and nested exception.
*
* The message can be parameterized using {}
as placeholders for the given
* arguments
*
* @param msg the detail message
* @param cause the nested exception
* @param args the arguments for the message
*/
public ElasticsearchException(String msg, Throwable cause, Object... args) {
super(LoggerMessageFormat.format(msg, args), cause);
}
@SuppressWarnings("this-escape")
public ElasticsearchException(StreamInput in) throws IOException {
super(in.readOptionalString(), in.readException());
readStackTrace(this, in);
headers.putAll(in.readMapOfLists(StreamInput::readString));
metadata.putAll(in.readMapOfLists(StreamInput::readString));
}
/**
* Adds a new piece of metadata with the given key.
* If the provided key is already present, the corresponding metadata will be replaced
*/
public void addMetadata(String key, String... values) {
addMetadata(key, Arrays.asList(values));
}
/**
* Adds a new piece of metadata with the given key.
* If the provided key is already present, the corresponding metadata will be replaced
*/
public void addMetadata(String key, List values) {
// we need to enforce this otherwise bw comp doesn't work properly, as "es." was the previous criteria to split headers in two sets
if (key.startsWith("es.") == false) {
throw new IllegalArgumentException("exception metadata must start with [es.], found [" + key + "] instead");
}
this.metadata.put(key, values);
}
/**
* Returns a set of all metadata keys on this exception
*/
public Set getMetadataKeys() {
return metadata.keySet();
}
/**
* Returns the list of metadata values for the given key or {@code null} if no metadata for the
* given key exists.
*/
public List getMetadata(String key) {
return metadata.get(key);
}
protected Map> getMetadata() {
return metadata;
}
/**
* Adds a new header with the given key.
* This method will replace existing header if a header with the same key already exists
*/
public void addHeader(String key, List value) {
// we need to enforce this otherwise bw comp doesn't work properly, as "es." was the previous criteria to split headers in two sets
if (key.startsWith("es.")) {
throw new IllegalArgumentException("exception headers must not start with [es.], found [" + key + "] instead");
}
this.headers.put(key, value);
}
/**
* Adds a new header with the given key.
* This method will replace existing header if a header with the same key already exists
*/
public void addHeader(String key, String... value) {
addHeader(key, Arrays.asList(value));
}
/**
* Returns a set of all header keys on this exception
*/
public Set getHeaderKeys() {
return headers.keySet();
}
/**
* Returns the list of header values for the given key or {@code null} if no header for the
* given key exists.
*/
public List getHeader(String key) {
return headers.get(key);
}
protected Map> getHeaders() {
return headers;
}
/**
* Returns the rest status code associated with this exception.
*/
public RestStatus status() {
Throwable cause = unwrapCause();
if (cause == this) {
return RestStatus.INTERNAL_SERVER_ERROR;
} else {
return ExceptionsHelper.status(cause);
}
}
/**
* Unwraps the actual cause from the exception for cases when the exception is a
* {@link ElasticsearchWrapperException}.
*
* @see ExceptionsHelper#unwrapCause(Throwable)
*/
public Throwable unwrapCause() {
return ExceptionsHelper.unwrapCause(this);
}
/**
* Return the detail message, including the message from the nested exception
* if there is one.
*/
public String getDetailedMessage() {
if (getCause() != null) {
StringBuilder sb = new StringBuilder();
sb.append(toString()).append("; ");
if (getCause() instanceof ElasticsearchException) {
sb.append(((ElasticsearchException) getCause()).getDetailedMessage());
} else {
sb.append(getCause());
}
return sb.toString();
} else {
return super.toString();
}
}
/**
* Retrieve the innermost cause of this exception, if none, returns the current exception.
*/
public Throwable getRootCause() {
Throwable rootCause = this;
Throwable cause = getCause();
while (cause != null && cause != rootCause) {
rootCause = cause;
cause = cause.getCause();
}
return rootCause;
}
@Override
public final void writeTo(StreamOutput out) throws IOException {
writeTo(out, createNestingFunction(0, () -> {}));
}
private static Writer createNestingFunction(int thisLevel, Runnable nestedExceptionLimitCallback) {
int nextLevel = thisLevel + 1;
return (o, t) -> {
writeException(t.getCause(), o, nextLevel, nestedExceptionLimitCallback);
writeStackTraces(t, o, (no, nt) -> writeException(nt, no, nextLevel, nestedExceptionLimitCallback));
};
}
protected void writeTo(StreamOutput out, Writer nestedExceptionsWriter) throws IOException {
out.writeOptionalString(this.getMessage());
nestedExceptionsWriter.write(out, this);
out.writeMap(headers, StreamOutput::writeStringCollection);
out.writeMap(metadata, StreamOutput::writeStringCollection);
}
public static ElasticsearchException readException(StreamInput input, int id) throws IOException {
CheckedFunction elasticsearchException = ID_TO_SUPPLIER.get(id);
if (elasticsearchException == null) {
if (id == 127 && input.getTransportVersion().before(TransportVersions.V_7_5_0)) {
// was SearchContextException
return new SearchException(input);
}
throw new IllegalStateException("unknown exception for id: " + id);
}
return elasticsearchException.apply(input);
}
/**
* Returns true
iff the given class is a registered for an exception to be read.
*/
public static boolean isRegistered(Class extends Throwable> exception, TransportVersion version) {
ElasticsearchExceptionHandle elasticsearchExceptionHandle = CLASS_TO_ELASTICSEARCH_EXCEPTION_HANDLE.get(exception);
if (elasticsearchExceptionHandle != null) {
return version.onOrAfter(elasticsearchExceptionHandle.versionAdded);
}
return false;
}
static Set> getRegisteredKeys() { // for testing
return CLASS_TO_ELASTICSEARCH_EXCEPTION_HANDLE.keySet();
}
/**
* Returns the serialization id the given exception.
*/
public static int getId(Class extends ElasticsearchException> exception) {
return CLASS_TO_ELASTICSEARCH_EXCEPTION_HANDLE.get(exception).id;
}
@Override
public final XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return toXContent(builder, params, 0);
}
/**
* Equivalent to {@link org.elasticsearch.xcontent.ToXContent#toXContent(XContentBuilder, Params)} except that it limits nesting depth
* so that it can avoid stackoverflow errors.
*/
protected XContentBuilder toXContent(XContentBuilder builder, Params params, int nestedLevel) throws IOException {
Throwable ex = ExceptionsHelper.unwrapCause(this);
if (ex != this) {
generateThrowableXContent(builder, params, this, nestedLevel);
} else {
innerToXContent(builder, params, this, getExceptionName(), getMessage(), headers, metadata, getCause(), nestedLevel);
}
return builder;
}
protected static void innerToXContent(
XContentBuilder builder,
Params params,
Throwable throwable,
String type,
String message,
Map> headers,
Map> metadata,
Throwable cause,
int nestedLevel
) throws IOException {
if (nestedLevel > MAX_NESTED_EXCEPTION_LEVEL) {
var terminalException = new IllegalStateException("too many nested exceptions");
builder.field(TYPE, getExceptionName(terminalException));
builder.field(REASON, terminalException.getMessage());
return;
}
builder.field(TYPE, type);
builder.field(REASON, message);
for (Map.Entry> entry : metadata.entrySet()) {
headerToXContent(builder, entry.getKey().substring("es.".length()), entry.getValue());
}
if (throwable instanceof ElasticsearchException exception) {
exception.metadataToXContent(builder, params);
}
if (params.paramAsBoolean(REST_EXCEPTION_SKIP_CAUSE, REST_EXCEPTION_SKIP_CAUSE_DEFAULT) == false) {
if (cause != null) {
builder.field(CAUSED_BY);
builder.startObject();
generateThrowableXContent(builder, params, cause, nestedLevel + 1);
builder.endObject();
}
}
if (headers.isEmpty() == false) {
builder.startObject(HEADER);
for (Map.Entry> entry : headers.entrySet()) {
headerToXContent(builder, entry.getKey(), entry.getValue());
}
builder.endObject();
}
if (params.paramAsBoolean(REST_EXCEPTION_SKIP_STACK_TRACE, REST_EXCEPTION_SKIP_STACK_TRACE_DEFAULT) == false) {
builder.field(STACK_TRACE, ExceptionsHelper.stackTrace(throwable));
}
Throwable[] allSuppressed = throwable.getSuppressed();
if (allSuppressed.length > 0) {
builder.startArray(SUPPRESSED.getPreferredName());
for (Throwable suppressed : allSuppressed) {
builder.startObject();
generateThrowableXContent(builder, params, suppressed, nestedLevel + 1);
builder.endObject();
}
builder.endArray();
}
}
private static void headerToXContent(XContentBuilder builder, String key, List values) throws IOException {
if (values != null && values.isEmpty() == false) {
if (values.size() == 1) {
builder.field(key, values.get(0));
} else {
builder.startArray(key);
for (String value : values) {
builder.value(value);
}
builder.endArray();
}
}
}
/**
* Renders additional per exception information into the XContent
*/
protected void metadataToXContent(XContentBuilder builder, Params params) throws IOException {}
/**
* Generate a {@link ElasticsearchException} from a {@link XContentParser}. This does not
* return the original exception type (ie NodeClosedException for example) but just wraps
* the type, the reason and the cause of the exception. It also recursively parses the
* tree structure of the cause, returning it as a tree structure of {@link ElasticsearchException}
* instances.
*/
public static ElasticsearchException fromXContent(XContentParser parser) throws IOException {
XContentParser.Token token = parser.nextToken();
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser);
return innerFromXContent(parser, false);
}
public static ElasticsearchException innerFromXContent(XContentParser parser, boolean parseRootCauses) throws IOException {
XContentParser.Token token = parser.currentToken();
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser);
String type = null, reason = null, stack = null;
ElasticsearchException cause = null;
Map> metadata = new HashMap<>();
Map> headers = new HashMap<>();
List rootCauses = new ArrayList<>();
List suppressed = new ArrayList<>();
for (; token == XContentParser.Token.FIELD_NAME; token = parser.nextToken()) {
String currentFieldName = parser.currentName();
token = parser.nextToken();
if (token.isValue()) {
if (TYPE.equals(currentFieldName)) {
type = parser.text();
} else if (REASON.equals(currentFieldName)) {
reason = parser.text();
} else if (STACK_TRACE.equals(currentFieldName)) {
stack = parser.text();
} else if (token == XContentParser.Token.VALUE_STRING) {
metadata.put(currentFieldName, Collections.singletonList(parser.text()));
}
} else if (token == XContentParser.Token.START_OBJECT) {
if (CAUSED_BY.equals(currentFieldName)) {
cause = fromXContent(parser);
} else if (HEADER.equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else {
List values = headers.getOrDefault(currentFieldName, new ArrayList<>());
if (token == XContentParser.Token.VALUE_STRING) {
values.add(parser.text());
} else if (token == XContentParser.Token.START_ARRAY) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
if (token == XContentParser.Token.VALUE_STRING) {
values.add(parser.text());
} else {
parser.skipChildren();
}
}
} else if (token == XContentParser.Token.START_OBJECT) {
parser.skipChildren();
}
headers.put(currentFieldName, values);
}
}
} else {
// Any additional metadata object added by the metadataToXContent method is ignored
// and skipped, so that the parser does not fail on unknown fields. The parser only
// support metadata key-pairs and metadata arrays of values.
parser.skipChildren();
}
} else if (token == XContentParser.Token.START_ARRAY) {
if (parseRootCauses && ROOT_CAUSE.equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
rootCauses.add(fromXContent(parser));
}
} else if (SUPPRESSED.match(currentFieldName, parser.getDeprecationHandler())) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
suppressed.add(fromXContent(parser));
}
} else {
// Parse the array and add each item to the corresponding list of metadata.
// Arrays of objects are not supported yet and just ignored and skipped.
List values = new ArrayList<>();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
if (token == XContentParser.Token.VALUE_STRING) {
values.add(parser.text());
} else {
parser.skipChildren();
}
}
if (values.size() > 0) {
if (metadata.containsKey(currentFieldName)) {
values.addAll(metadata.get(currentFieldName));
}
metadata.put(currentFieldName, values);
}
}
}
}
ElasticsearchException e = new ElasticsearchException(buildMessage(type, reason, stack), cause);
for (Map.Entry> entry : metadata.entrySet()) {
// subclasses can print out additional metadata through the metadataToXContent method. Simple key-value pairs will be
// parsed back and become part of this metadata set, while objects and arrays are not supported when parsing back.
// Those key-value pairs become part of the metadata set and inherit the "es." prefix as that is currently required
// by addMetadata. The prefix will get stripped out when printing metadata out so it will be effectively invisible.
// TODO move subclasses that print out simple metadata to using addMetadata directly and support also numbers and booleans.
// TODO rename metadataToXContent and have only SearchPhaseExecutionException use it, which prints out complex objects
e.addMetadata("es." + entry.getKey(), entry.getValue());
}
for (Map.Entry> header : headers.entrySet()) {
e.addHeader(header.getKey(), header.getValue());
}
// Adds root causes as suppressed exception. This way they are not lost
// after parsing and can be retrieved using getSuppressed() method.
for (ElasticsearchException rootCause : rootCauses) {
e.addSuppressed(rootCause);
}
for (ElasticsearchException s : suppressed) {
e.addSuppressed(s);
}
return e;
}
/**
* Static toXContent helper method that renders {@link org.elasticsearch.ElasticsearchException} or {@link Throwable} instances
* as XContent, delegating the rendering to {@link #toXContent(XContentBuilder, Params)}
* or {@link #innerToXContent(XContentBuilder, Params, Throwable, String, String, Map, Map, Throwable, int)}.
*
* This method is usually used when the {@link Throwable} is rendered as a part of another XContent object, and its result can
* be parsed back using the {@link #fromXContent(XContentParser)} method.
*/
public static void generateThrowableXContent(XContentBuilder builder, Params params, Throwable t) throws IOException {
generateThrowableXContent(builder, params, t, 0);
}
/**
* Equivalent to {@link #generateThrowableXContent(XContentBuilder, Params, Throwable)} but limits nesting depth
* so that it can avoid stackoverflow errors.
*/
protected static void generateThrowableXContent(XContentBuilder builder, Params params, Throwable t, int nestedLevel)
throws IOException {
t = ExceptionsHelper.unwrapCause(t);
if (t instanceof ElasticsearchException) {
((ElasticsearchException) t).toXContent(builder, params, nestedLevel);
} else {
innerToXContent(builder, params, t, getExceptionName(t), t.getMessage(), emptyMap(), emptyMap(), t.getCause(), nestedLevel);
}
}
/**
* Render any exception as a xcontent, encapsulated within a field or object named "error". The level of details that are rendered
* depends on the value of the "detailed" parameter: when it's false only a simple message based on the type and message of the
* exception is rendered. When it's true all detail are provided including guesses root causes, cause and potentially stack
* trace.
*
* This method is usually used when the {@link Exception} is rendered as a full XContent object, and its output can be parsed
* by the {@link #failureFromXContent(XContentParser)} method.
*/
public static XContentBuilder generateFailureXContent(XContentBuilder builder, Params params, @Nullable Exception e, boolean detailed)
throws IOException {
// No exception to render as an error
if (e == null) {
return builder.field(ERROR, "unknown");
}
// Render the exception with a simple message
if (detailed == false) {
String message = "No ElasticsearchException found";
Throwable t = e;
for (int counter = 0; counter < 10 && t != null; counter++) {
if (t instanceof ElasticsearchException) {
message = t.getClass().getSimpleName() + "[" + t.getMessage() + "]";
break;
}
t = t.getCause();
}
return builder.field(ERROR, message);
}
// Render the exception with all details
final ElasticsearchException[] rootCauses = ElasticsearchException.guessRootCauses(e);
builder.startObject(ERROR);
{
builder.startArray(ROOT_CAUSE);
for (ElasticsearchException rootCause : rootCauses) {
builder.startObject();
rootCause.toXContent(builder, new DelegatingMapParams(singletonMap(REST_EXCEPTION_SKIP_CAUSE, "true"), params));
builder.endObject();
}
builder.endArray();
}
generateThrowableXContent(builder, params, e);
return builder.endObject();
}
/**
* Parses the output of {@link #generateFailureXContent(XContentBuilder, Params, Exception, boolean)}
*/
public static ElasticsearchException failureFromXContent(XContentParser parser) throws IOException {
XContentParser.Token token = parser.currentToken();
ensureFieldName(parser, token, ERROR);
token = parser.nextToken();
if (token.isValue()) {
return new ElasticsearchException(buildMessage("exception", parser.text(), null));
}
ensureExpectedToken(XContentParser.Token.START_OBJECT, token, parser);
token = parser.nextToken();
// Root causes are parsed in the innerFromXContent() and are added as suppressed exceptions.
return innerFromXContent(parser, true);
}
/**
* Returns the root cause of this exception or multiple if different shards caused different exceptions
*/
public ElasticsearchException[] guessRootCauses() {
final Throwable cause = getCause();
if (cause != null && cause instanceof ElasticsearchException) {
return ((ElasticsearchException) cause).guessRootCauses();
}
return new ElasticsearchException[] { this };
}
/**
* Returns the root cause of this exception or multiple if different shards caused different exceptions.
* If the given exception is not an instance of {@link org.elasticsearch.ElasticsearchException} an empty array
* is returned.
*/
public static ElasticsearchException[] guessRootCauses(Throwable t) {
Throwable ex = ExceptionsHelper.unwrapCause(t);
if (ex instanceof ElasticsearchException) {
// ElasticsearchException knows how to guess its own root cause
return ((ElasticsearchException) ex).guessRootCauses();
}
if (ex instanceof XContentParseException) {
/*
* We'd like to unwrap parsing exceptions to the inner-most
* parsing exception because that is generally the most interesting
* exception to return to the user. If that exception is caused by
* an ElasticsearchException we'd like to keep unwrapping because
* ElasticsearchExceptions tend to contain useful information for
* the user.
*/
Throwable cause = ex.getCause();
if (cause != null) {
if (cause instanceof XContentParseException || cause instanceof ElasticsearchException) {
return guessRootCauses(ex.getCause());
}
}
}
return new ElasticsearchException[] { new ElasticsearchException(ex.getMessage(), ex) {
@Override
protected String getExceptionName() {
return getExceptionName(getCause());
}
} };
}
protected String getExceptionName() {
return getExceptionName(this);
}
/**
* Returns a underscore case name for the given exception. This method strips {@code Elasticsearch} prefixes from exception names.
*/
public static String getExceptionName(Throwable ex) {
String simpleName = ex.getClass().getSimpleName();
if (simpleName.startsWith("Elasticsearch")) {
simpleName = simpleName.substring("Elasticsearch".length());
}
// TODO: do we really need to make the exception name in underscore casing?
return toUnderscoreCase(simpleName);
}
static String buildMessage(String type, String reason, String stack) {
StringBuilder message = new StringBuilder("Elasticsearch exception [");
message.append(TYPE).append('=').append(type).append(", ");
message.append(REASON).append('=').append(reason);
if (stack != null) {
message.append(", ").append(STACK_TRACE).append('=').append(stack);
}
message.append(']');
return message.toString();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (metadata.containsKey(INDEX_METADATA_KEY)) {
builder.append(getIndex());
if (metadata.containsKey(SHARD_METADATA_KEY)) {
builder.append('[').append(getShardId()).append(']');
}
builder.append(' ');
}
return builder.append(super.toString().trim()).toString();
}
/**
* Deserializes stacktrace elements as well as suppressed exceptions from the given output stream and
* adds it to the given exception.
*/
public static T readStackTrace(T throwable, StreamInput in) throws IOException {
throwable.setStackTrace(in.readArray(i -> {
final String declaringClasss = i.readString();
final String fileName = i.readOptionalString();
final String methodName = i.readString();
final int lineNumber = i.readVInt();
return new StackTraceElement(declaringClasss, methodName, fileName, lineNumber);
}, StackTraceElement[]::new));
int numSuppressed = in.readVInt();
for (int i = 0; i < numSuppressed; i++) {
throwable.addSuppressed(in.readException());
}
return throwable;
}
/**
* Serializes the given exceptions stacktrace elements as well as it's suppressed exceptions to the given output stream.
*/
public static void writeStackTraces(Throwable throwable, StreamOutput out, Writer exceptionWriter) throws IOException {
out.writeArray((o, v) -> {
o.writeString(v.getClassName());
o.writeOptionalString(v.getFileName());
o.writeString(v.getMethodName());
o.writeVInt(v.getLineNumber());
}, throwable.getStackTrace());
out.writeArray(exceptionWriter, throwable.getSuppressed());
}
/**
* Writes the specified {@code throwable} to {@link StreamOutput} {@code output}.
*/
public static void writeException(Throwable throwable, StreamOutput output) throws IOException {
writeException(throwable, output, () -> {});
}
static void writeException(Throwable throwable, StreamOutput output, Runnable nestedExceptionLimitCallback) throws IOException {
writeException(throwable, output, 0, nestedExceptionLimitCallback);
}
private static final int MAX_NESTED_EXCEPTION_LEVEL = 100;
private static void writeException(Throwable throwable, StreamOutput output, int nestedLevel, Runnable nestedExceptionLimitCallback)
throws IOException {
if (nestedLevel > MAX_NESTED_EXCEPTION_LEVEL) {
nestedExceptionLimitCallback.run();
writeException(new IllegalStateException("too many nested exceptions"), output);
return;
}
if (throwable == null) {
output.writeBoolean(false);
return;
}
output.writeBoolean(true);
boolean writeCause = true;
boolean writeMessage = true;
if (throwable instanceof CorruptIndexException cie) {
output.writeVInt(1);
output.writeOptionalString(cie.getOriginalMessage());
output.writeOptionalString(cie.getResourceDescription());
writeMessage = false;
} else if (throwable instanceof IndexFormatTooNewException iftne) {
output.writeVInt(2);
output.writeOptionalString(iftne.getResourceDescription());
output.writeInt(iftne.getVersion());
output.writeInt(iftne.getMinVersion());
output.writeInt(iftne.getMaxVersion());
writeMessage = false;
writeCause = false;
} else if (throwable instanceof IndexFormatTooOldException t) {
output.writeVInt(3);
output.writeOptionalString(t.getResourceDescription());
if (t.getVersion() == null) {
output.writeBoolean(false);
output.writeOptionalString(t.getReason());
} else {
output.writeBoolean(true);
output.writeInt(t.getVersion());
output.writeInt(t.getMinVersion());
output.writeInt(t.getMaxVersion());
}
writeMessage = false;
writeCause = false;
} else if (throwable instanceof NullPointerException) {
output.writeVInt(4);
writeCause = false;
} else if (throwable instanceof NumberFormatException) {
output.writeVInt(5);
writeCause = false;
} else if (throwable instanceof IllegalArgumentException) {
output.writeVInt(6);
} else if (throwable instanceof AlreadyClosedException) {
output.writeVInt(7);
} else if (throwable instanceof EOFException) {
output.writeVInt(8);
writeCause = false;
} else if (throwable instanceof SecurityException) {
output.writeVInt(9);
} else if (throwable instanceof StringIndexOutOfBoundsException) {
output.writeVInt(10);
writeCause = false;
} else if (throwable instanceof ArrayIndexOutOfBoundsException) {
output.writeVInt(11);
writeCause = false;
} else if (throwable instanceof FileNotFoundException) {
output.writeVInt(12);
writeCause = false;
} else if (throwable instanceof FileSystemException fse) {
output.writeVInt(13);
if (throwable instanceof NoSuchFileException) {
output.writeVInt(0);
} else if (throwable instanceof NotDirectoryException) {
output.writeVInt(1);
} else if (throwable instanceof DirectoryNotEmptyException) {
output.writeVInt(2);
} else if (throwable instanceof AtomicMoveNotSupportedException) {
output.writeVInt(3);
} else if (throwable instanceof FileAlreadyExistsException) {
output.writeVInt(4);
} else if (throwable instanceof AccessDeniedException) {
output.writeVInt(5);
} else if (throwable instanceof FileSystemLoopException) {
output.writeVInt(6);
} else {
output.writeVInt(7);
}
output.writeOptionalString(fse.getFile());
output.writeOptionalString(fse.getOtherFile());
output.writeOptionalString(fse.getReason());
writeCause = false;
} else if (throwable instanceof IllegalStateException) {
output.writeVInt(14);
} else if (throwable instanceof LockObtainFailedException) {
output.writeVInt(15);
} else if (throwable instanceof InterruptedException) {
output.writeVInt(16);
writeCause = false;
} else if (throwable instanceof IOException) {
output.writeVInt(17);
} else if (throwable instanceof EsRejectedExecutionException eree) {
output.writeVInt(18);
output.writeBoolean(eree.isExecutorShutdown());
writeCause = false;
} else {
ElasticsearchException ex;
if (throwable instanceof ElasticsearchException ee && isRegistered(throwable.getClass(), output.getTransportVersion())) {
ex = ee;
} else {
ex = new NotSerializableExceptionWrapper(throwable);
}
output.writeVInt(0);
output.writeVInt(getId(ex.getClass()));
ex.writeTo(output, createNestingFunction(nestedLevel, nestedExceptionLimitCallback));
return;
}
if (writeMessage) {
output.writeOptionalString(throwable.getMessage());
}
if (writeCause) {
writeException(throwable.getCause(), output, nestedLevel + 1, nestedExceptionLimitCallback);
}
writeStackTraces(throwable, output, (o, t) -> writeException(t, o, nestedLevel + 1, nestedExceptionLimitCallback));
}
/**
* Reads a {@code Throwable} from {@link StreamInput} {@code input}.
*/
@Nullable
@SuppressWarnings("unchecked")
public static T readException(StreamInput input) throws IOException {
if (input.readBoolean()) {
int key = input.readVInt();
switch (key) {
case 0:
int ord = input.readVInt();
return (T) readException(input, ord);
case 1:
String msg1 = input.readOptionalString();
String resource1 = input.readOptionalString();
return (T) readStackTrace(new CorruptIndexException(msg1, resource1, readException(input)), input);
case 2:
String resource2 = input.readOptionalString();
int version2 = input.readInt();
int minVersion2 = input.readInt();
int maxVersion2 = input.readInt();
return (T) readStackTrace(new IndexFormatTooNewException(resource2, version2, minVersion2, maxVersion2), input);
case 3:
String resource3 = input.readOptionalString();
if (input.readBoolean()) {
int version3 = input.readInt();
int minVersion3 = input.readInt();
int maxVersion3 = input.readInt();
return (T) readStackTrace(new IndexFormatTooOldException(resource3, version3, minVersion3, maxVersion3), input);
} else {
String version3 = input.readOptionalString();
return (T) readStackTrace(new IndexFormatTooOldException(resource3, version3), input);
}
case 4:
return (T) readStackTrace(new NullPointerException(input.readOptionalString()), input);
case 5:
return (T) readStackTrace(new NumberFormatException(input.readOptionalString()), input);
case 6:
return (T) readStackTrace(new IllegalArgumentException(input.readOptionalString(), readException(input)), input);
case 7:
return (T) readStackTrace(new AlreadyClosedException(input.readOptionalString(), readException(input)), input);
case 8:
return (T) readStackTrace(new EOFException(input.readOptionalString()), input);
case 9:
return (T) readStackTrace(new SecurityException(input.readOptionalString(), readException(input)), input);
case 10:
return (T) readStackTrace(new StringIndexOutOfBoundsException(input.readOptionalString()), input);
case 11:
return (T) readStackTrace(new ArrayIndexOutOfBoundsException(input.readOptionalString()), input);
case 12:
return (T) readStackTrace(new FileNotFoundException(input.readOptionalString()), input);
case 13:
int subclass = input.readVInt();
String file = input.readOptionalString();
String other = input.readOptionalString();
String reason = input.readOptionalString();
input.readOptionalString(); // skip the msg - it's composed from file, other and reason
Exception exception = switch (subclass) {
case 0 -> new NoSuchFileException(file, other, reason);
case 1 -> new NotDirectoryException(file);
case 2 -> new DirectoryNotEmptyException(file);
case 3 -> new AtomicMoveNotSupportedException(file, other, reason);
case 4 -> new FileAlreadyExistsException(file, other, reason);
case 5 -> new AccessDeniedException(file, other, reason);
case 6 -> new FileSystemLoopException(file);
case 7 -> new FileSystemException(file, other, reason);
default -> throw new IllegalStateException("unknown FileSystemException with index " + subclass);
};
return (T) readStackTrace(exception, input);
case 14:
return (T) readStackTrace(new IllegalStateException(input.readOptionalString(), readException(input)), input);
case 15:
return (T) readStackTrace(new LockObtainFailedException(input.readOptionalString(), readException(input)), input);
case 16:
return (T) readStackTrace(new InterruptedException(input.readOptionalString()), input);
case 17:
return (T) readStackTrace(new IOException(input.readOptionalString(), readException(input)), input);
case 18:
boolean isExecutorShutdown = input.readBoolean();
return (T) readStackTrace(new EsRejectedExecutionException(input.readOptionalString(), isExecutorShutdown), input);
default:
throw new IOException("no such exception for id: " + key);
}
}
return null;
}
/**
* This is the list of Exceptions Elasticsearch can throw over the wire or save into a corruption marker. Each value in the enum is a
* single exception tying the Class to an id for use of the encode side and the id back to a constructor for use on the decode side. As
* such it's ok if the exceptions to change names so long as their constructor can still read the exception. Each exception is listed
* in id order below. If you want to remove an exception leave a tombstone comment and mark the id as null in
* ExceptionSerializationTests.testIds.ids.
*/
private enum ElasticsearchExceptionHandle {
INDEX_SHARD_SNAPSHOT_FAILED_EXCEPTION(
org.elasticsearch.index.snapshots.IndexShardSnapshotFailedException.class,
org.elasticsearch.index.snapshots.IndexShardSnapshotFailedException::new,
0,
UNKNOWN_VERSION_ADDED
),
DFS_PHASE_EXECUTION_EXCEPTION(
org.elasticsearch.search.dfs.DfsPhaseExecutionException.class,
org.elasticsearch.search.dfs.DfsPhaseExecutionException::new,
1,
UNKNOWN_VERSION_ADDED
),
EXECUTION_CANCELLED_EXCEPTION(
org.elasticsearch.common.util.CancellableThreads.ExecutionCancelledException.class,
org.elasticsearch.common.util.CancellableThreads.ExecutionCancelledException::new,
2,
UNKNOWN_VERSION_ADDED
),
MASTER_NOT_DISCOVERED_EXCEPTION(
org.elasticsearch.discovery.MasterNotDiscoveredException.class,
org.elasticsearch.discovery.MasterNotDiscoveredException::new,
3,
UNKNOWN_VERSION_ADDED
),
ELASTICSEARCH_SECURITY_EXCEPTION(
org.elasticsearch.ElasticsearchSecurityException.class,
org.elasticsearch.ElasticsearchSecurityException::new,
4,
UNKNOWN_VERSION_ADDED
),
INDEX_SHARD_RESTORE_EXCEPTION(
org.elasticsearch.index.snapshots.IndexShardRestoreException.class,
org.elasticsearch.index.snapshots.IndexShardRestoreException::new,
5,
UNKNOWN_VERSION_ADDED
),
INDEX_CLOSED_EXCEPTION(
org.elasticsearch.indices.IndexClosedException.class,
org.elasticsearch.indices.IndexClosedException::new,
6,
UNKNOWN_VERSION_ADDED
),
BIND_HTTP_EXCEPTION(
org.elasticsearch.http.BindHttpException.class,
org.elasticsearch.http.BindHttpException::new,
7,
UNKNOWN_VERSION_ADDED
),
REDUCE_SEARCH_PHASE_EXCEPTION(
org.elasticsearch.action.search.ReduceSearchPhaseException.class,
org.elasticsearch.action.search.ReduceSearchPhaseException::new,
8,
UNKNOWN_VERSION_ADDED
),
NODE_CLOSED_EXCEPTION(
org.elasticsearch.node.NodeClosedException.class,
org.elasticsearch.node.NodeClosedException::new,
9,
UNKNOWN_VERSION_ADDED
),
// 10 was for SnapshotFailedEngineException, never instantiated in 6.2.0+ and never thrown across clusters
SHARD_NOT_FOUND_EXCEPTION(
org.elasticsearch.index.shard.ShardNotFoundException.class,
org.elasticsearch.index.shard.ShardNotFoundException::new,
11,
UNKNOWN_VERSION_ADDED
),
CONNECT_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.ConnectTransportException.class,
org.elasticsearch.transport.ConnectTransportException::new,
12,
UNKNOWN_VERSION_ADDED
),
NOT_SERIALIZABLE_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.NotSerializableTransportException.class,
org.elasticsearch.transport.NotSerializableTransportException::new,
13,
UNKNOWN_VERSION_ADDED
),
RESPONSE_HANDLER_FAILURE_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.ResponseHandlerFailureTransportException.class,
org.elasticsearch.transport.ResponseHandlerFailureTransportException::new,
14,
UNKNOWN_VERSION_ADDED
),
INDEX_CREATION_EXCEPTION(
org.elasticsearch.indices.IndexCreationException.class,
org.elasticsearch.indices.IndexCreationException::new,
15,
UNKNOWN_VERSION_ADDED
),
INDEX_NOT_FOUND_EXCEPTION(
org.elasticsearch.index.IndexNotFoundException.class,
org.elasticsearch.index.IndexNotFoundException::new,
16,
UNKNOWN_VERSION_ADDED
),
ILLEGAL_SHARD_ROUTING_STATE_EXCEPTION(
org.elasticsearch.cluster.routing.IllegalShardRoutingStateException.class,
org.elasticsearch.cluster.routing.IllegalShardRoutingStateException::new,
17,
UNKNOWN_VERSION_ADDED
),
BROADCAST_SHARD_OPERATION_FAILED_EXCEPTION(
org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException.class,
org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException::new,
18,
UNKNOWN_VERSION_ADDED
),
RESOURCE_NOT_FOUND_EXCEPTION(
org.elasticsearch.ResourceNotFoundException.class,
org.elasticsearch.ResourceNotFoundException::new,
19,
UNKNOWN_VERSION_ADDED
),
ACTION_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.ActionTransportException.class,
org.elasticsearch.transport.ActionTransportException::new,
20,
UNKNOWN_VERSION_ADDED
),
ELASTICSEARCH_GENERATION_EXCEPTION(
org.elasticsearch.ElasticsearchGenerationException.class,
org.elasticsearch.ElasticsearchGenerationException::new,
21,
UNKNOWN_VERSION_ADDED
),
// 22 was CreateFailedEngineException
INDEX_SHARD_STARTED_EXCEPTION(
org.elasticsearch.index.shard.IndexShardStartedException.class,
org.elasticsearch.index.shard.IndexShardStartedException::new,
23,
UNKNOWN_VERSION_ADDED
),
SEARCH_CONTEXT_MISSING_EXCEPTION(
org.elasticsearch.search.SearchContextMissingException.class,
org.elasticsearch.search.SearchContextMissingException::new,
24,
UNKNOWN_VERSION_ADDED
),
GENERAL_SCRIPT_EXCEPTION(
org.elasticsearch.script.GeneralScriptException.class,
org.elasticsearch.script.GeneralScriptException::new,
25,
UNKNOWN_VERSION_ADDED
),
// 26 was BatchOperationException
// 27 was SnapshotCreationException
// 28 was DeleteFailedEngineException, deprecated in 6.0, removed in 7.0
DOCUMENT_MISSING_EXCEPTION(
org.elasticsearch.index.engine.DocumentMissingException.class,
org.elasticsearch.index.engine.DocumentMissingException::new,
29,
UNKNOWN_VERSION_ADDED
),
SNAPSHOT_EXCEPTION(
org.elasticsearch.snapshots.SnapshotException.class,
org.elasticsearch.snapshots.SnapshotException::new,
30,
UNKNOWN_VERSION_ADDED
),
INVALID_ALIAS_NAME_EXCEPTION(
org.elasticsearch.indices.InvalidAliasNameException.class,
org.elasticsearch.indices.InvalidAliasNameException::new,
31,
UNKNOWN_VERSION_ADDED
),
INVALID_INDEX_NAME_EXCEPTION(
org.elasticsearch.indices.InvalidIndexNameException.class,
org.elasticsearch.indices.InvalidIndexNameException::new,
32,
UNKNOWN_VERSION_ADDED
),
INDEX_PRIMARY_SHARD_NOT_ALLOCATED_EXCEPTION(
org.elasticsearch.indices.IndexPrimaryShardNotAllocatedException.class,
org.elasticsearch.indices.IndexPrimaryShardNotAllocatedException::new,
33,
UNKNOWN_VERSION_ADDED
),
TRANSPORT_EXCEPTION(
org.elasticsearch.transport.TransportException.class,
org.elasticsearch.transport.TransportException::new,
34,
UNKNOWN_VERSION_ADDED
),
ELASTICSEARCH_PARSE_EXCEPTION(
org.elasticsearch.ElasticsearchParseException.class,
org.elasticsearch.ElasticsearchParseException::new,
35,
UNKNOWN_VERSION_ADDED
),
SEARCH_EXCEPTION(
org.elasticsearch.search.SearchException.class,
org.elasticsearch.search.SearchException::new,
36,
UNKNOWN_VERSION_ADDED
),
MAPPER_EXCEPTION(
org.elasticsearch.index.mapper.MapperException.class,
org.elasticsearch.index.mapper.MapperException::new,
37,
UNKNOWN_VERSION_ADDED
),
INVALID_TYPE_NAME_EXCEPTION(
org.elasticsearch.indices.InvalidTypeNameException.class,
org.elasticsearch.indices.InvalidTypeNameException::new,
38,
UNKNOWN_VERSION_ADDED
),
SNAPSHOT_RESTORE_EXCEPTION(
org.elasticsearch.snapshots.SnapshotRestoreException.class,
org.elasticsearch.snapshots.SnapshotRestoreException::new,
39,
UNKNOWN_VERSION_ADDED
),
PARSING_EXCEPTION(
org.elasticsearch.common.ParsingException.class,
org.elasticsearch.common.ParsingException::new,
40,
UNKNOWN_VERSION_ADDED
),
INDEX_SHARD_CLOSED_EXCEPTION(
org.elasticsearch.index.shard.IndexShardClosedException.class,
org.elasticsearch.index.shard.IndexShardClosedException::new,
41,
UNKNOWN_VERSION_ADDED
),
RECOVER_FILES_RECOVERY_EXCEPTION(
org.elasticsearch.indices.recovery.RecoverFilesRecoveryException.class,
org.elasticsearch.indices.recovery.RecoverFilesRecoveryException::new,
42,
UNKNOWN_VERSION_ADDED
),
TRUNCATED_TRANSLOG_EXCEPTION(
org.elasticsearch.index.translog.TruncatedTranslogException.class,
org.elasticsearch.index.translog.TruncatedTranslogException::new,
43,
UNKNOWN_VERSION_ADDED
),
RECOVERY_FAILED_EXCEPTION(
org.elasticsearch.indices.recovery.RecoveryFailedException.class,
org.elasticsearch.indices.recovery.RecoveryFailedException::new,
44,
UNKNOWN_VERSION_ADDED
),
INDEX_SHARD_RELOCATED_EXCEPTION(
org.elasticsearch.index.shard.IndexShardRelocatedException.class,
org.elasticsearch.index.shard.IndexShardRelocatedException::new,
45,
UNKNOWN_VERSION_ADDED
),
// 46 was for NodeShouldNotConnectException, never instantiated in 5.0+
// 47 used to be for IndexTemplateAlreadyExistsException which was deprecated in 5.1 removed in 6.0
TRANSLOG_CORRUPTED_EXCEPTION(
org.elasticsearch.index.translog.TranslogCorruptedException.class,
org.elasticsearch.index.translog.TranslogCorruptedException::new,
48,
UNKNOWN_VERSION_ADDED
),
CLUSTER_BLOCK_EXCEPTION(
org.elasticsearch.cluster.block.ClusterBlockException.class,
org.elasticsearch.cluster.block.ClusterBlockException::new,
49,
UNKNOWN_VERSION_ADDED
),
FETCH_PHASE_EXECUTION_EXCEPTION(
org.elasticsearch.search.fetch.FetchPhaseExecutionException.class,
org.elasticsearch.search.fetch.FetchPhaseExecutionException::new,
50,
UNKNOWN_VERSION_ADDED
),
// 51 used to be for IndexShardAlreadyExistsException which was deprecated in 5.1 removed in 6.0
VERSION_CONFLICT_ENGINE_EXCEPTION(
org.elasticsearch.index.engine.VersionConflictEngineException.class,
org.elasticsearch.index.engine.VersionConflictEngineException::new,
52,
UNKNOWN_VERSION_ADDED
),
ENGINE_EXCEPTION(
org.elasticsearch.index.engine.EngineException.class,
org.elasticsearch.index.engine.EngineException::new,
53,
UNKNOWN_VERSION_ADDED
),
// 54 was DocumentAlreadyExistsException, which is superseded by VersionConflictEngineException
NO_SUCH_NODE_EXCEPTION(
org.elasticsearch.action.NoSuchNodeException.class,
org.elasticsearch.action.NoSuchNodeException::new,
55,
UNKNOWN_VERSION_ADDED
),
SETTINGS_EXCEPTION(
org.elasticsearch.common.settings.SettingsException.class,
org.elasticsearch.common.settings.SettingsException::new,
56,
UNKNOWN_VERSION_ADDED
),
INDEX_TEMPLATE_MISSING_EXCEPTION(
org.elasticsearch.indices.IndexTemplateMissingException.class,
org.elasticsearch.indices.IndexTemplateMissingException::new,
57,
UNKNOWN_VERSION_ADDED
),
SEND_REQUEST_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.SendRequestTransportException.class,
org.elasticsearch.transport.SendRequestTransportException::new,
58,
UNKNOWN_VERSION_ADDED
),
// 59 used to be EsRejectedExecutionException
// 60 used to be for EarlyTerminationException
// 61 used to be for RoutingValidationException
NOT_SERIALIZABLE_EXCEPTION_WRAPPER(
org.elasticsearch.common.io.stream.NotSerializableExceptionWrapper.class,
org.elasticsearch.common.io.stream.NotSerializableExceptionWrapper::new,
62,
UNKNOWN_VERSION_ADDED
),
ALIAS_FILTER_PARSING_EXCEPTION(
org.elasticsearch.indices.AliasFilterParsingException.class,
org.elasticsearch.indices.AliasFilterParsingException::new,
63,
UNKNOWN_VERSION_ADDED
),
// 64 was DeleteByQueryFailedEngineException, which was removed in 5.0
// 65 was for GatewayException, never instantiated in 5.0+
INDEX_SHARD_NOT_RECOVERING_EXCEPTION(
org.elasticsearch.index.shard.IndexShardNotRecoveringException.class,
org.elasticsearch.index.shard.IndexShardNotRecoveringException::new,
66,
UNKNOWN_VERSION_ADDED
),
HTTP_EXCEPTION(org.elasticsearch.http.HttpException.class, org.elasticsearch.http.HttpException::new, 67, UNKNOWN_VERSION_ADDED),
ELASTICSEARCH_EXCEPTION(
org.elasticsearch.ElasticsearchException.class,
org.elasticsearch.ElasticsearchException::new,
68,
UNKNOWN_VERSION_ADDED
),
SNAPSHOT_MISSING_EXCEPTION(
org.elasticsearch.snapshots.SnapshotMissingException.class,
org.elasticsearch.snapshots.SnapshotMissingException::new,
69,
UNKNOWN_VERSION_ADDED
),
PRIMARY_MISSING_ACTION_EXCEPTION(
org.elasticsearch.action.PrimaryMissingActionException.class,
org.elasticsearch.action.PrimaryMissingActionException::new,
70,
UNKNOWN_VERSION_ADDED
),
FAILED_NODE_EXCEPTION(
org.elasticsearch.action.FailedNodeException.class,
org.elasticsearch.action.FailedNodeException::new,
71,
UNKNOWN_VERSION_ADDED
),
// 72 was SearchParseException, only used in tests after 7.11
CONCURRENT_SNAPSHOT_EXECUTION_EXCEPTION(
org.elasticsearch.snapshots.ConcurrentSnapshotExecutionException.class,
org.elasticsearch.snapshots.ConcurrentSnapshotExecutionException::new,
73,
UNKNOWN_VERSION_ADDED
),
BLOB_STORE_EXCEPTION(
org.elasticsearch.common.blobstore.BlobStoreException.class,
org.elasticsearch.common.blobstore.BlobStoreException::new,
74,
UNKNOWN_VERSION_ADDED
),
INCOMPATIBLE_CLUSTER_STATE_VERSION_EXCEPTION(
org.elasticsearch.cluster.IncompatibleClusterStateVersionException.class,
org.elasticsearch.cluster.IncompatibleClusterStateVersionException::new,
75,
UNKNOWN_VERSION_ADDED
),
RECOVERY_ENGINE_EXCEPTION(
org.elasticsearch.index.engine.RecoveryEngineException.class,
org.elasticsearch.index.engine.RecoveryEngineException::new,
76,
UNKNOWN_VERSION_ADDED
),
UNCATEGORIZED_EXECUTION_EXCEPTION(
org.elasticsearch.common.util.concurrent.UncategorizedExecutionException.class,
org.elasticsearch.common.util.concurrent.UncategorizedExecutionException::new,
77,
UNKNOWN_VERSION_ADDED
),
TIMESTAMP_PARSING_EXCEPTION(
org.elasticsearch.action.TimestampParsingException.class,
org.elasticsearch.action.TimestampParsingException::new,
78,
UNKNOWN_VERSION_ADDED
),
ROUTING_MISSING_EXCEPTION(
org.elasticsearch.action.RoutingMissingException.class,
org.elasticsearch.action.RoutingMissingException::new,
79,
UNKNOWN_VERSION_ADDED
),
// 80 was IndexFailedEngineException, deprecated in 6.0, removed in 7.0
INDEX_SHARD_RESTORE_FAILED_EXCEPTION(
org.elasticsearch.index.snapshots.IndexShardRestoreFailedException.class,
org.elasticsearch.index.snapshots.IndexShardRestoreFailedException::new,
81,
UNKNOWN_VERSION_ADDED
),
REPOSITORY_EXCEPTION(
org.elasticsearch.repositories.RepositoryException.class,
org.elasticsearch.repositories.RepositoryException::new,
82,
UNKNOWN_VERSION_ADDED
),
RECEIVE_TIMEOUT_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.ReceiveTimeoutTransportException.class,
org.elasticsearch.transport.ReceiveTimeoutTransportException::new,
83,
UNKNOWN_VERSION_ADDED
),
NODE_DISCONNECTED_EXCEPTION(
org.elasticsearch.transport.NodeDisconnectedException.class,
org.elasticsearch.transport.NodeDisconnectedException::new,
84,
UNKNOWN_VERSION_ADDED
),
// 85 used to be for AlreadyExpiredException
AGGREGATION_EXECUTION_EXCEPTION(
org.elasticsearch.search.aggregations.AggregationExecutionException.class,
org.elasticsearch.search.aggregations.AggregationExecutionException::new,
86,
UNKNOWN_VERSION_ADDED
),
// 87 used to be for MergeMappingException
INVALID_INDEX_TEMPLATE_EXCEPTION(
org.elasticsearch.indices.InvalidIndexTemplateException.class,
org.elasticsearch.indices.InvalidIndexTemplateException::new,
88,
UNKNOWN_VERSION_ADDED
),
REFRESH_FAILED_ENGINE_EXCEPTION(
org.elasticsearch.index.engine.RefreshFailedEngineException.class,
org.elasticsearch.index.engine.RefreshFailedEngineException::new,
90,
UNKNOWN_VERSION_ADDED
),
AGGREGATION_INITIALIZATION_EXCEPTION(
org.elasticsearch.search.aggregations.AggregationInitializationException.class,
org.elasticsearch.search.aggregations.AggregationInitializationException::new,
91,
UNKNOWN_VERSION_ADDED
),
DELAY_RECOVERY_EXCEPTION(
org.elasticsearch.indices.recovery.DelayRecoveryException.class,
org.elasticsearch.indices.recovery.DelayRecoveryException::new,
92,
UNKNOWN_VERSION_ADDED
),
// 93 used to be for IndexWarmerMissingException
NO_NODE_AVAILABLE_EXCEPTION(
org.elasticsearch.client.internal.transport.NoNodeAvailableException.class,
org.elasticsearch.client.internal.transport.NoNodeAvailableException::new,
94,
UNKNOWN_VERSION_ADDED
),
INVALID_SNAPSHOT_NAME_EXCEPTION(
org.elasticsearch.snapshots.InvalidSnapshotNameException.class,
org.elasticsearch.snapshots.InvalidSnapshotNameException::new,
96,
UNKNOWN_VERSION_ADDED
),
ILLEGAL_INDEX_SHARD_STATE_EXCEPTION(
org.elasticsearch.index.shard.IllegalIndexShardStateException.class,
org.elasticsearch.index.shard.IllegalIndexShardStateException::new,
97,
UNKNOWN_VERSION_ADDED
),
INDEX_SHARD_SNAPSHOT_EXCEPTION(
org.elasticsearch.index.snapshots.IndexShardSnapshotException.class,
org.elasticsearch.index.snapshots.IndexShardSnapshotException::new,
98,
UNKNOWN_VERSION_ADDED
),
INDEX_SHARD_NOT_STARTED_EXCEPTION(
org.elasticsearch.index.shard.IndexShardNotStartedException.class,
org.elasticsearch.index.shard.IndexShardNotStartedException::new,
99,
UNKNOWN_VERSION_ADDED
),
SEARCH_PHASE_EXECUTION_EXCEPTION(
org.elasticsearch.action.search.SearchPhaseExecutionException.class,
org.elasticsearch.action.search.SearchPhaseExecutionException::new,
100,
UNKNOWN_VERSION_ADDED
),
ACTION_NOT_FOUND_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.ActionNotFoundTransportException.class,
org.elasticsearch.transport.ActionNotFoundTransportException::new,
101,
UNKNOWN_VERSION_ADDED
),
TRANSPORT_SERIALIZATION_EXCEPTION(
org.elasticsearch.transport.TransportSerializationException.class,
org.elasticsearch.transport.TransportSerializationException::new,
102,
UNKNOWN_VERSION_ADDED
),
REMOTE_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.RemoteTransportException.class,
org.elasticsearch.transport.RemoteTransportException::new,
103,
UNKNOWN_VERSION_ADDED
),
ENGINE_CREATION_FAILURE_EXCEPTION(
org.elasticsearch.index.engine.EngineCreationFailureException.class,
org.elasticsearch.index.engine.EngineCreationFailureException::new,
104,
UNKNOWN_VERSION_ADDED
),
ROUTING_EXCEPTION(
org.elasticsearch.cluster.routing.RoutingException.class,
org.elasticsearch.cluster.routing.RoutingException::new,
105,
UNKNOWN_VERSION_ADDED
),
INDEX_SHARD_RECOVERY_EXCEPTION(
org.elasticsearch.index.shard.IndexShardRecoveryException.class,
org.elasticsearch.index.shard.IndexShardRecoveryException::new,
106,
UNKNOWN_VERSION_ADDED
),
REPOSITORY_MISSING_EXCEPTION(
org.elasticsearch.repositories.RepositoryMissingException.class,
org.elasticsearch.repositories.RepositoryMissingException::new,
107,
UNKNOWN_VERSION_ADDED
),
DOCUMENT_SOURCE_MISSING_EXCEPTION(
org.elasticsearch.index.engine.DocumentSourceMissingException.class,
org.elasticsearch.index.engine.DocumentSourceMissingException::new,
109,
UNKNOWN_VERSION_ADDED
),
// 110 used to be FlushNotAllowedEngineException
NO_CLASS_SETTINGS_EXCEPTION(
org.elasticsearch.common.settings.NoClassSettingsException.class,
org.elasticsearch.common.settings.NoClassSettingsException::new,
111,
UNKNOWN_VERSION_ADDED
),
BIND_TRANSPORT_EXCEPTION(
org.elasticsearch.transport.BindTransportException.class,
org.elasticsearch.transport.BindTransportException::new,
112,
UNKNOWN_VERSION_ADDED
),
ALIASES_NOT_FOUND_EXCEPTION(
org.elasticsearch.rest.action.admin.indices.AliasesNotFoundException.class,
org.elasticsearch.rest.action.admin.indices.AliasesNotFoundException::new,
113,
UNKNOWN_VERSION_ADDED
),
INDEX_SHARD_RECOVERING_EXCEPTION(
org.elasticsearch.index.shard.IndexShardRecoveringException.class,
org.elasticsearch.index.shard.IndexShardRecoveringException::new,
114,
UNKNOWN_VERSION_ADDED
),
TRANSLOG_EXCEPTION(
org.elasticsearch.index.translog.TranslogException.class,
org.elasticsearch.index.translog.TranslogException::new,
115,
UNKNOWN_VERSION_ADDED
),
PROCESS_CLUSTER_EVENT_TIMEOUT_EXCEPTION(
org.elasticsearch.cluster.metadata.ProcessClusterEventTimeoutException.class,
org.elasticsearch.cluster.metadata.ProcessClusterEventTimeoutException::new,
116,
UNKNOWN_VERSION_ADDED
),
RETRY_ON_PRIMARY_EXCEPTION(
ReplicationOperation.RetryOnPrimaryException.class,
ReplicationOperation.RetryOnPrimaryException::new,
117,
UNKNOWN_VERSION_ADDED
),
ELASTICSEARCH_TIMEOUT_EXCEPTION(
org.elasticsearch.ElasticsearchTimeoutException.class,
org.elasticsearch.ElasticsearchTimeoutException::new,
118,
UNKNOWN_VERSION_ADDED
),
QUERY_PHASE_EXECUTION_EXCEPTION(
org.elasticsearch.search.query.QueryPhaseExecutionException.class,
org.elasticsearch.search.query.QueryPhaseExecutionException::new,
119,
UNKNOWN_VERSION_ADDED
),
REPOSITORY_VERIFICATION_EXCEPTION(
org.elasticsearch.repositories.RepositoryVerificationException.class,
org.elasticsearch.repositories.RepositoryVerificationException::new,
120,
UNKNOWN_VERSION_ADDED
),
INVALID_AGGREGATION_PATH_EXCEPTION(
org.elasticsearch.search.aggregations.InvalidAggregationPathException.class,
org.elasticsearch.search.aggregations.InvalidAggregationPathException::new,
121,
UNKNOWN_VERSION_ADDED
),
// 123 used to be IndexAlreadyExistsException and was renamed
RESOURCE_ALREADY_EXISTS_EXCEPTION(
ResourceAlreadyExistsException.class,
ResourceAlreadyExistsException::new,
123,
UNKNOWN_VERSION_ADDED
),
// 124 used to be Script.ScriptParseException
HTTP_REQUEST_ON_TRANSPORT_EXCEPTION(
TcpTransport.HttpRequestOnTransportException.class,
TcpTransport.HttpRequestOnTransportException::new,
125,
UNKNOWN_VERSION_ADDED
),
MAPPER_PARSING_EXCEPTION(
org.elasticsearch.index.mapper.MapperParsingException.class,
org.elasticsearch.index.mapper.MapperParsingException::new,
126,
UNKNOWN_VERSION_ADDED
),
// 127 used to be org.elasticsearch.search.SearchContextException
SEARCH_SOURCE_BUILDER_EXCEPTION(
org.elasticsearch.search.builder.SearchSourceBuilderException.class,
org.elasticsearch.search.builder.SearchSourceBuilderException::new,
128,
UNKNOWN_VERSION_ADDED
),
// 129 was EngineClosedException
NO_SHARD_AVAILABLE_ACTION_EXCEPTION(
org.elasticsearch.action.NoShardAvailableActionException.class,
org.elasticsearch.action.NoShardAvailableActionException::new,
130,
UNKNOWN_VERSION_ADDED
),
UNAVAILABLE_SHARDS_EXCEPTION(
org.elasticsearch.action.UnavailableShardsException.class,
org.elasticsearch.action.UnavailableShardsException::new,
131,
UNKNOWN_VERSION_ADDED
),
FLUSH_FAILED_ENGINE_EXCEPTION(
org.elasticsearch.index.engine.FlushFailedEngineException.class,
org.elasticsearch.index.engine.FlushFailedEngineException::new,
132,
UNKNOWN_VERSION_ADDED
),
CIRCUIT_BREAKING_EXCEPTION(
org.elasticsearch.common.breaker.CircuitBreakingException.class,
org.elasticsearch.common.breaker.CircuitBreakingException::new,
133,
UNKNOWN_VERSION_ADDED
),
NODE_NOT_CONNECTED_EXCEPTION(
org.elasticsearch.transport.NodeNotConnectedException.class,
org.elasticsearch.transport.NodeNotConnectedException::new,
134,
UNKNOWN_VERSION_ADDED
),
STRICT_DYNAMIC_MAPPING_EXCEPTION(
org.elasticsearch.index.mapper.StrictDynamicMappingException.class,
org.elasticsearch.index.mapper.StrictDynamicMappingException::new,
135,
UNKNOWN_VERSION_ADDED
),
RETRY_ON_REPLICA_EXCEPTION(
org.elasticsearch.action.support.replication.TransportReplicationAction.RetryOnReplicaException.class,
org.elasticsearch.action.support.replication.TransportReplicationAction.RetryOnReplicaException::new,
136,
UNKNOWN_VERSION_ADDED
),
TYPE_MISSING_EXCEPTION(
org.elasticsearch.indices.TypeMissingException.class,
org.elasticsearch.indices.TypeMissingException::new,
137,
UNKNOWN_VERSION_ADDED
),
FAILED_TO_COMMIT_CLUSTER_STATE_EXCEPTION(
org.elasticsearch.cluster.coordination.FailedToCommitClusterStateException.class,
org.elasticsearch.cluster.coordination.FailedToCommitClusterStateException::new,
140,
UNKNOWN_VERSION_ADDED
),
QUERY_SHARD_EXCEPTION(
org.elasticsearch.index.query.QueryShardException.class,
org.elasticsearch.index.query.QueryShardException::new,
141,
UNKNOWN_VERSION_ADDED
),
NO_LONGER_PRIMARY_SHARD_EXCEPTION(
ShardStateAction.NoLongerPrimaryShardException.class,
ShardStateAction.NoLongerPrimaryShardException::new,
142,
UNKNOWN_VERSION_ADDED
),
SCRIPT_EXCEPTION(
org.elasticsearch.script.ScriptException.class,
org.elasticsearch.script.ScriptException::new,
143,
UNKNOWN_VERSION_ADDED
),
NOT_MASTER_EXCEPTION(
org.elasticsearch.cluster.NotMasterException.class,
org.elasticsearch.cluster.NotMasterException::new,
144,
UNKNOWN_VERSION_ADDED
),
STATUS_EXCEPTION(
org.elasticsearch.ElasticsearchStatusException.class,
org.elasticsearch.ElasticsearchStatusException::new,
145,
UNKNOWN_VERSION_ADDED
),
TASK_CANCELLED_EXCEPTION(
org.elasticsearch.tasks.TaskCancelledException.class,
org.elasticsearch.tasks.TaskCancelledException::new,
146,
UNKNOWN_VERSION_ADDED
),
SHARD_LOCK_OBTAIN_FAILED_EXCEPTION(
org.elasticsearch.env.ShardLockObtainFailedException.class,
org.elasticsearch.env.ShardLockObtainFailedException::new,
147,
UNKNOWN_VERSION_ADDED
),
// 148 was UnknownNamedObjectException
TOO_MANY_BUCKETS_EXCEPTION(
MultiBucketConsumerService.TooManyBucketsException.class,
MultiBucketConsumerService.TooManyBucketsException::new,
149,
UNKNOWN_VERSION_ADDED
),
COORDINATION_STATE_REJECTED_EXCEPTION(
org.elasticsearch.cluster.coordination.CoordinationStateRejectedException.class,
org.elasticsearch.cluster.coordination.CoordinationStateRejectedException::new,
150,
TransportVersions.V_7_0_0
),
SNAPSHOT_IN_PROGRESS_EXCEPTION(
org.elasticsearch.snapshots.SnapshotInProgressException.class,
org.elasticsearch.snapshots.SnapshotInProgressException::new,
151,
UNKNOWN_VERSION_ADDED
),
NO_SUCH_REMOTE_CLUSTER_EXCEPTION(
org.elasticsearch.transport.NoSuchRemoteClusterException.class,
org.elasticsearch.transport.NoSuchRemoteClusterException::new,
152,
UNKNOWN_VERSION_ADDED
),
RETENTION_LEASE_ALREADY_EXISTS_EXCEPTION(
org.elasticsearch.index.seqno.RetentionLeaseAlreadyExistsException.class,
org.elasticsearch.index.seqno.RetentionLeaseAlreadyExistsException::new,
153,
UNKNOWN_VERSION_ADDED
),
RETENTION_LEASE_NOT_FOUND_EXCEPTION(
org.elasticsearch.index.seqno.RetentionLeaseNotFoundException.class,
org.elasticsearch.index.seqno.RetentionLeaseNotFoundException::new,
154,
UNKNOWN_VERSION_ADDED
),
SHARD_NOT_IN_PRIMARY_MODE_EXCEPTION(
org.elasticsearch.index.shard.ShardNotInPrimaryModeException.class,
org.elasticsearch.index.shard.ShardNotInPrimaryModeException::new,
155,
UNKNOWN_VERSION_ADDED
),
RETENTION_LEASE_INVALID_RETAINING_SEQUENCE_NUMBER_EXCEPTION(
org.elasticsearch.index.seqno.RetentionLeaseInvalidRetainingSeqNoException.class,
org.elasticsearch.index.seqno.RetentionLeaseInvalidRetainingSeqNoException::new,
156,
TransportVersions.V_7_5_0
),
INGEST_PROCESSOR_EXCEPTION(
org.elasticsearch.ingest.IngestProcessorException.class,
org.elasticsearch.ingest.IngestProcessorException::new,
157,
TransportVersions.V_7_5_0
),
PEER_RECOVERY_NOT_FOUND_EXCEPTION(
org.elasticsearch.indices.recovery.PeerRecoveryNotFound.class,
org.elasticsearch.indices.recovery.PeerRecoveryNotFound::new,
158,
TransportVersions.V_7_9_0
),
NODE_HEALTH_CHECK_FAILURE_EXCEPTION(
org.elasticsearch.cluster.coordination.NodeHealthCheckFailureException.class,
org.elasticsearch.cluster.coordination.NodeHealthCheckFailureException::new,
159,
TransportVersions.V_8_0_0
),
NO_SEED_NODE_LEFT_EXCEPTION(
org.elasticsearch.transport.NoSeedNodeLeftException.class,
org.elasticsearch.transport.NoSeedNodeLeftException::new,
160,
TransportVersions.V_7_10_0
),
VERSION_MISMATCH_EXCEPTION(
org.elasticsearch.action.search.VersionMismatchException.class,
org.elasticsearch.action.search.VersionMismatchException::new,
161,
TransportVersions.V_7_12_0
),
AUTHENTICATION_PROCESSING_ERROR(
org.elasticsearch.ElasticsearchAuthenticationProcessingError.class,
org.elasticsearch.ElasticsearchAuthenticationProcessingError::new,
162,
TransportVersions.V_7_16_0
),
REPOSITORY_CONFLICT_EXCEPTION(
org.elasticsearch.repositories.RepositoryConflictException.class,
org.elasticsearch.repositories.RepositoryConflictException::new,
163,
TransportVersions.V_8_0_0
),
DESIRED_NODES_VERSION_CONFLICT_EXCEPTION(
org.elasticsearch.cluster.desirednodes.VersionConflictException.class,
org.elasticsearch.cluster.desirednodes.VersionConflictException::new,
164,
TransportVersions.V_8_1_0
),
SNAPSHOT_NAME_ALREADY_IN_USE_EXCEPTION(
org.elasticsearch.snapshots.SnapshotNameAlreadyInUseException.class,
org.elasticsearch.snapshots.SnapshotNameAlreadyInUseException::new,
165,
TransportVersions.V_8_2_0
),
HEALTH_NODE_NOT_DISCOVERED_EXCEPTION(
HealthNodeNotDiscoveredException.class,
HealthNodeNotDiscoveredException::new,
166,
TransportVersions.V_8_5_0
),
UNSUPPORTED_AGGREGATION_ON_DOWNSAMPLED_INDEX_EXCEPTION(
UnsupportedAggregationOnDownsampledIndex.class,
UnsupportedAggregationOnDownsampledIndex::new,
167,
TransportVersions.V_8_5_0
),
DOCUMENT_PARSING_EXCEPTION(DocumentParsingException.class, DocumentParsingException::new, 168, TransportVersions.V_8_8_0),
HTTP_HEADERS_VALIDATION_EXCEPTION(
org.elasticsearch.http.HttpHeadersValidationException.class,
org.elasticsearch.http.HttpHeadersValidationException::new,
169,
TransportVersions.V_8_9_X
),
ROLE_RESTRICTION_EXCEPTION(
ElasticsearchRoleRestrictionException.class,
ElasticsearchRoleRestrictionException::new,
170,
TransportVersions.V_8_9_X
),
API_NOT_AVAILABLE_EXCEPTION(ApiNotAvailableException.class, ApiNotAvailableException::new, 171, TransportVersions.V_8_11_X),
RECOVERY_COMMIT_TOO_NEW_EXCEPTION(
RecoveryCommitTooNewException.class,
RecoveryCommitTooNewException::new,
172,
TransportVersions.V_8_11_X
),
TOO_MANY_SCROLL_CONTEXTS_NEW_EXCEPTION(
TooManyScrollContextsException.class,
TooManyScrollContextsException::new,
173,
TransportVersions.V_8_12_0
),
INVALID_BUCKET_PATH_EXCEPTION(
AggregationExecutionException.InvalidPath.class,
AggregationExecutionException.InvalidPath::new,
174,
TransportVersions.V_8_12_0
),
MISSED_INDICES_UPDATE_EXCEPTION(
AutoscalingMissedIndicesUpdateException.class,
AutoscalingMissedIndicesUpdateException::new,
175,
TransportVersions.V_8_12_0
),
SEARCH_TIMEOUT_EXCEPTION(SearchTimeoutException.class, SearchTimeoutException::new, 176, TransportVersions.V_8_13_0),
INGEST_GRAPH_STRUCTURE_EXCEPTION(GraphStructureException.class, GraphStructureException::new, 177, TransportVersions.V_8_13_0),
FAILURE_INDEX_NOT_SUPPORTED_EXCEPTION(
FailureIndexNotSupportedException.class,
FailureIndexNotSupportedException::new,
178,
TransportVersions.ADD_FAILURE_STORE_INDICES_OPTIONS
),
NOT_PERSISTENT_TASK_NODE_EXCEPTION(
NotPersistentTaskNodeException.class,
NotPersistentTaskNodeException::new,
179,
TransportVersions.ADD_PERSISTENT_TASK_EXCEPTIONS
),
PERSISTENT_TASK_NODE_NOT_ASSIGNED_EXCEPTION(
PersistentTaskNodeNotAssignedException.class,
PersistentTaskNodeNotAssignedException::new,
180,
TransportVersions.ADD_PERSISTENT_TASK_EXCEPTIONS
),
RESOURCE_ALREADY_UPLOADED_EXCEPTION(
ResourceAlreadyUploadedException.class,
ResourceAlreadyUploadedException::new,
181,
TransportVersions.ADD_RESOURCE_ALREADY_UPLOADED_EXCEPTION
);
final Class extends ElasticsearchException> exceptionClass;
final CheckedFunction constructor;
final int id;
final TransportVersion versionAdded;
ElasticsearchExceptionHandle(
Class exceptionClass,
CheckedFunction constructor,
int id,
TransportVersion versionAdded
) {
// We need the exceptionClass because you can't dig it out of the constructor reliably.
this.exceptionClass = exceptionClass;
this.constructor = constructor;
this.versionAdded = versionAdded;
this.id = id;
}
}
/**
* Returns an array of all registered handle IDs. These are the IDs for every registered
* exception.
*
* @return an array of all registered handle IDs
*/
static int[] ids() {
return Arrays.stream(ElasticsearchExceptionHandle.values()).mapToInt(h -> h.id).toArray();
}
/**
* Returns an array of all registered pairs of handle IDs and exception classes. These pairs are
* provided for every registered exception.
*
* @return an array of all registered pairs of handle IDs and exception classes
*/
static Tuple>[] classes() {
@SuppressWarnings("unchecked")
final Tuple>[] ts = Arrays.stream(ElasticsearchExceptionHandle.values())
.map(h -> Tuple.tuple(h.id, h.exceptionClass))
.toArray(Tuple[]::new);
return ts;
}
static {
ID_TO_SUPPLIER = unmodifiableMap(
Arrays.stream(ElasticsearchExceptionHandle.values()).collect(Collectors.toMap(e -> e.id, e -> e.constructor))
);
CLASS_TO_ELASTICSEARCH_EXCEPTION_HANDLE = unmodifiableMap(
Arrays.stream(ElasticsearchExceptionHandle.values()).collect(Collectors.toMap(e -> e.exceptionClass, e -> e))
);
}
public Index getIndex() {
List index = getMetadata(INDEX_METADATA_KEY);
if (index != null && index.isEmpty() == false) {
List index_uuid = getMetadata(INDEX_METADATA_KEY_UUID);
return new Index(index.get(0), index_uuid.get(0));
}
return null;
}
public ShardId getShardId() {
List shard = getMetadata(SHARD_METADATA_KEY);
if (shard != null && shard.isEmpty() == false) {
return new ShardId(getIndex(), Integer.parseInt(shard.get(0)));
}
return null;
}
public void setIndex(Index index) {
if (index != null) {
addMetadata(INDEX_METADATA_KEY, index.getName());
addMetadata(INDEX_METADATA_KEY_UUID, index.getUUID());
}
}
public void setIndex(String index) {
if (index != null) {
setIndex(new Index(index, INDEX_UUID_NA_VALUE));
}
}
public void setShard(ShardId shardId) {
if (shardId != null) {
setIndex(shardId.getIndex());
addMetadata(SHARD_METADATA_KEY, Integer.toString(shardId.id()));
}
}
public void setResources(String type, String... id) {
assert type != null;
addMetadata(RESOURCE_METADATA_ID_KEY, id);
addMetadata(RESOURCE_METADATA_TYPE_KEY, type);
}
public List getResourceId() {
return getMetadata(RESOURCE_METADATA_ID_KEY);
}
public String getResourceType() {
List header = getMetadata(RESOURCE_METADATA_TYPE_KEY);
if (header != null && header.isEmpty() == false) {
assert header.size() == 1;
return header.get(0);
}
return null;
}
// lower cases and adds underscores to transitions in a name
private static String toUnderscoreCase(String value) {
StringBuilder sb = new StringBuilder();
boolean changed = false;
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (Character.isUpperCase(c)) {
if (changed == false) {
// copy it over here
for (int j = 0; j < i; j++) {
sb.append(value.charAt(j));
}
changed = true;
if (i == 0) {
sb.append(Character.toLowerCase(c));
} else {
sb.append('_');
sb.append(Character.toLowerCase(c));
}
} else {
sb.append('_');
sb.append(Character.toLowerCase(c));
}
} else {
if (changed) {
sb.append(c);
}
}
}
if (changed == false) {
return value;
}
return sb.toString();
}
}