@@ -131,7 +131,6 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
131131 @ SuppressWarnings ("this-escape" )
132132 public ElasticsearchException (Throwable cause ) {
133133 super (cause );
134- addErrorHeaders ();
135134 }
136135
137136 /**
@@ -146,7 +145,6 @@ public ElasticsearchException(Throwable cause) {
146145 @ SuppressWarnings ("this-escape" )
147146 public ElasticsearchException (String msg , Object ... args ) {
148147 super (LoggerMessageFormat .format (msg , args ));
149- addErrorHeaders ();
150148 }
151149
152150 /**
@@ -163,7 +161,6 @@ public ElasticsearchException(String msg, Object... args) {
163161 @ SuppressWarnings ("this-escape" )
164162 public ElasticsearchException (String msg , Throwable cause , Object ... args ) {
165163 super (LoggerMessageFormat .format (msg , args ), cause );
166- addErrorHeaders ();
167164 }
168165
169166 @ SuppressWarnings ("this-escape" )
@@ -174,16 +171,18 @@ public ElasticsearchException(StreamInput in) throws IOException {
174171 metadata .putAll (in .readMapOfLists (StreamInput ::readString ));
175172 }
176173
177- private void addErrorHeaders () {
178- if (isTimeout ()) {
174+ private void maybeAddErrorHeaders () {
175+ if (isTimeout () && headers . containsKey ( TIMED_OUT_HEADER ) == false ) {
179176 // see https://www.rfc-editor.org/rfc/rfc8941.html#section-4.1.9 for booleans in structured headers
180177 headers .put (TIMED_OUT_HEADER , List .of ("?1" ));
181178 }
182- // TODO: cache unwrapping the cause? we do this in several places...
183- Throwable cause = unwrapCause ();
184- RestStatus status = ExceptionsHelper .status (cause );
185- if (status .getStatus () >= 500 ) {
186- headers .put (EXCEPTION_TYPE_HEADER , List .of (cause .getClass ().getSimpleName ()));
179+ if (headers .containsKey (EXCEPTION_TYPE_HEADER ) == false ) {
180+ // TODO: cache unwrapping the cause? we do this in several places...
181+ Throwable cause = unwrapCause ();
182+ RestStatus status = ExceptionsHelper .status (cause );
183+ if (status .getStatus () >= 500 ) {
184+ headers .put (EXCEPTION_TYPE_HEADER , List .of (cause .getClass ().getSimpleName ()));
185+ }
187186 }
188187 }
189188
@@ -250,6 +249,7 @@ public void addHeader(String key, String... value) {
250249 * Returns a set of all header keys on this exception
251250 */
252251 public Set <String > getHeaderKeys () {
252+ maybeAddErrorHeaders ();
253253 return headers .keySet ();
254254 }
255255
@@ -258,10 +258,12 @@ public Set<String> getHeaderKeys() {
258258 * given key exists.
259259 */
260260 public List <String > getHeader (String key ) {
261+ maybeAddErrorHeaders ();
261262 return headers .get (key );
262263 }
263264
264265 protected Map <String , List <String >> getHeaders () {
266+ maybeAddErrorHeaders ();
265267 return headers ;
266268 }
267269
@@ -342,7 +344,7 @@ private static Writer<Throwable> createNestingFunction(int thisLevel, Runnable n
342344 protected void writeTo (StreamOutput out , Writer <Throwable > nestedExceptionsWriter ) throws IOException {
343345 out .writeOptionalString (this .getMessage ());
344346 nestedExceptionsWriter .write (out , this );
345- out .writeMap (headers , StreamOutput ::writeStringCollection );
347+ out .writeMap (getHeaders () , StreamOutput ::writeStringCollection );
346348 out .writeMap (metadata , StreamOutput ::writeStringCollection );
347349 }
348350
@@ -391,7 +393,7 @@ protected XContentBuilder toXContent(XContentBuilder builder, Params params, int
391393 if (ex != this ) {
392394 generateThrowableXContent (builder , params , this , nestedLevel );
393395 } else {
394- innerToXContent (builder , params , this , headers , metadata , getCause (), nestedLevel );
396+ innerToXContent (builder , params , this , getHeaders () , metadata , getCause (), nestedLevel );
395397 }
396398 return builder ;
397399 }
0 commit comments