Spring Cloud: 4.0.0-RC3

After restarting Eureka server, application which uses RestTemplateEurekaHttpClient cannot be registered anymore to eureka until itself (client application) is restarted.

Relevant part of log in client application after restarting eureka server:

15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 >> PUT /eureka/apps/MSG-GW-CORE/msg-gw-core-01?status=UP&lastDirtyTimestamp=1670248378143 HTTP/1.1
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 >> Accept: application/json, application/*+json
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 >> Accept-Encoding: gzip, x-gzip, deflate
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 >> Content-Length: 0
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 >> Host: 127.0.0.1:8761
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 >> Connection: keep-alive
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 >> User-Agent: Apache-HttpClient/5.1.4 (Java/17.0.5)
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 >> "PUT /eureka/apps/MSG-GW-CORE/msg-gw-core-01?status=UP&lastDirtyTimestamp=1670248378143 HTTP/1.1[\r][\n]"
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 >> "Accept: application/json, application/*+json[\r][\n]"
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 >> "Accept-Encoding: gzip, x-gzip, deflate[\r][\n]"
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 >> "Content-Length: 0[\r][\n]"
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 >> "Host: 127.0.0.1:8761[\r][\n]"
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 >> "Connection: keep-alive[\r][\n]"
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 >> "User-Agent: Apache-HttpClient/5.1.4 (Java/17.0.5)[\r][\n]"
15:11:59.832 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 >> "[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "HTTP/1.1 404 [\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "Content-Type: application/json[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "Transfer-Encoding: chunked[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "Date: Mon, 05 Dec 2022 14:11:59 GMT[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "Keep-Alive: timeout=60[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "Connection: keep-alive[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "7f[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "{"timestamp":"2022-12-05T14:11:59.833+00:00","status":404,"error":"Not Found","path":"/eureka/apps/MSG-GW-CORE/msg-gw-core-01"}[\r][\n]"
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 << HTTP/1.1 404 
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 << Content-Type: application/json
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 << Transfer-Encoding: chunked
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 << Date: Mon, 05 Dec 2022 14:11:59 GMT
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 << Keep-Alive: timeout=60
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-219 << Connection: keep-alive
15:11:59.834 DEBUG [DiscoveryClient-HeartbeatExecutor-0]    o.a.h.c.h.impl.classic.MainClientExec : ex-0000000254 connection can be kept alive for 60 SECONDS
15:11:59.835 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "0[\r][\n]"
15:11:59.835 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-219 << "[\r][\n]"
15:11:59.835 DEBUG [DiscoveryClient-HeartbeatExecutor-0]   o.a.h.c.h.i.classic.InternalHttpClient : ep-0000000254 releasing valid endpoint
15:11:59.835 DEBUG [DiscoveryClient-HeartbeatExecutor-0] o.a.h.c.h.i.i.PoolingHttpClientConnectionManager : ep-0000000254 releasing endpoint
15:11:59.835 DEBUG [DiscoveryClient-HeartbeatExecutor-0] o.a.h.c.h.i.i.PoolingHttpClientConnectionManager : ep-0000000254 connection http-outgoing-219 can be kept alive for 60 SECONDS
15:11:59.835 DEBUG [DiscoveryClient-HeartbeatExecutor-0] o.a.h.c.h.i.i.PoolingHttpClientConnectionManager : ep-0000000254 connection released [route: {}->http://127.0.0.1:8761][total available: 1; route allocated: 1 of 5; total allocated: 1 of 25]
15:11:59.835  INFO [DiscoveryClient-HeartbeatExecutor-0]  c.n.d.s.t.d.RedirectingEurekaHttpClient : Request execution error. endpoint=DefaultEndpoint{ serviceUrl='http://127.0.0.1:8761/eureka/}, exception=Error while extracting response for type [class com.netflix.appinfo.InstanceInfo] and content type [application/json] stacktrace=org.springframework.web.client.RestClientException: Error while extracting response for type [class com.netflix.appinfo.InstanceInfo] and content type [application/json]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:118)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1132)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1115)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:865)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:764)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:646)
    at org.springframework.cloud.netflix.eureka.http.RestTemplateEurekaHttpClient.sendHeartBeat(RestTemplateEurekaHttpClient.java:99)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.executeOnNewServer(RedirectingEurekaHttpClient.java:121)
    at com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient.execute(RedirectingEurekaHttpClient.java:80)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:120)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    at com.netflix.discovery.DiscoveryClient.renew(DiscoveryClient.java:837)
    at com.netflix.discovery.DiscoveryClient$HeartbeatThread.run(DiscoveryClient.java:1401)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Root name ('timestamp') does not match expected ('instance') for type `com.netflix.appinfo.InstanceInfo`
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:406)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:354)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:103)
    ... 24 more
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Root name ('timestamp') does not match expected ('instance') for type `com.netflix.appinfo.InstanceInfo`
 at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 2] (through reference chain: com.netflix.appinfo.InstanceInfo["timestamp"])
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportPropertyInputMismatch(DeserializationContext.java:1781)
    at com.fasterxml.jackson.databind.DeserializationContext.reportPropertyInputMismatch(DeserializationContext.java:1797)
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext._unwrapAndDeserialize(DefaultDeserializationContext.java:348)
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:320)
    at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:2105)
    at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1481)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:395)
    ... 26 more

15:11:59.835  WARN [DiscoveryClient-HeartbeatExecutor-0]    c.n.d.s.t.d.RetryableEurekaHttpClient : Request execution failed with message: Error while extracting response for type [class com.netflix.appinfo.InstanceInfo] and content type [application/json]
15:11:59.835 ERROR [DiscoveryClient-HeartbeatExecutor-0]    com.netflix.discovery.DiscoveryClient : DiscoveryClient_MSG-GW-CORE/msg-gw-core-01 - was unable to send heartbeat!

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
    at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:112)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$3.execute(EurekaHttpClientDecorator.java:92)
    at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77)
    at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.sendHeartBeat(EurekaHttpClientDecorator.java:89)
    at com.netflix.discovery.DiscoveryClient.renew(DiscoveryClient.java:837)
    at com.netflix.discovery.DiscoveryClient$HeartbeatThread.run(DiscoveryClient.java:1401)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)

If I understood it correctly, RestTemplateEurekaHttpClient receives 404 and ignores error to continue with parsing response, according to ErrorHandler implementation, https://github.com/spring-cloud/spring-cloud-netflix/blob/23b594e5ecec481adbd134a344ba6054fa9862bf/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateTransportClientFactory.java#L203-L214

DiscoveryClient on 404 is performing re-registering apps https://github.com/Netflix/eureka/blob/191cc407cac86afe6633ddf44de3c37166fd318f/eureka-client/src/main/java/com/netflix/discovery/DiscoveryClient.java#L895-L903

but since RestTemplate has failed at reading response, 404 is not propagated to DiscoveryClient.

On older versions (Spring Boot < 3.0.0) this was working OK.

Comment From: ztomic

Well, probably it is issue because of some change in Spring Boot 3, I have same issue with client apps on Spring Boot 2.7.x connecting to Eureka Server on Spring Boot 3.0.0, possible some change with error handling in Spring Boot / Spring

Comment From: ztomic

Before Spring Boot 3, 404 from eureka server is without body

15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 >> PUT /eureka/apps/MSG-GW-CORE/msg-gw-core-01?status=UP&lastDirtyTimestamp=1670251882718 HTTP/1.1
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 >> Accept: application/json, application/x-jackson-smile, application/cbor, application/*+json
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 >> Content-Length: 0
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 >> Host: 127.0.0.1:8761
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 >> Connection: Keep-Alive
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 >> User-Agent: Apache-HttpClient/4.5.13 (Java/17.0.5)
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 >> Accept-Encoding: gzip,deflate
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 >> "PUT /eureka/apps/MSG-GW-CORE/msg-gw-core-01?status=UP&lastDirtyTimestamp=1670251882718 HTTP/1.1[\r][\n]"
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 >> "Accept: application/json, application/x-jackson-smile, application/cbor, application/*+json[\r][\n]"
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 >> "Content-Length: 0[\r][\n]"
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 >> "Host: 127.0.0.1:8761[\r][\n]"
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 >> "Connection: Keep-Alive[\r][\n]"
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 >> "User-Agent: Apache-HttpClient/4.5.13 (Java/17.0.5)[\r][\n]"
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 >> "Accept-Encoding: gzip,deflate[\r][\n]"
15:52:18.065 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 >> "[\r][\n]"
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 << "HTTP/1.1 404 [\r][\n]"
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 << "Content-Type: application/json[\r][\n]"
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 << "Content-Length: 0[\r][\n]"
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 << "Date: Mon, 05 Dec 2022 14:52:18 GMT[\r][\n]"
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 << "Keep-Alive: timeout=60[\r][\n]"
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 << "Connection: keep-alive[\r][\n]"
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                     org.apache.http.wire : http-outgoing-10 << "[\r][\n]"
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 << HTTP/1.1 404 
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 << Content-Type: application/json
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 << Content-Length: 0
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 << Date: Mon, 05 Dec 2022 14:52:18 GMT
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 << Keep-Alive: timeout=60
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]                  org.apache.http.headers : http-outgoing-10 << Connection: keep-alive
15:52:18.125 DEBUG [DiscoveryClient-HeartbeatExecutor-0]   o.a.http.impl.execchain.MainClientExec : Connection can be kept alive for 60000 MILLISECONDS
15:52:18.126 DEBUG [DiscoveryClient-HeartbeatExecutor-0] o.a.h.i.c.PoolingHttpClientConnectionManager : Connection [id: 10][route: {}->http://127.0.0.1:8761] can be kept alive for 60.0 seconds
15:52:18.126 DEBUG [DiscoveryClient-HeartbeatExecutor-0] o.a.h.i.c.DefaultManagedHttpClientConnection : http-outgoing-10: set socket timeout to 0
15:52:18.126 DEBUG [DiscoveryClient-HeartbeatExecutor-0] o.a.h.i.c.PoolingHttpClientConnectionManager : Connection released: [id: 10][route: {}->http://127.0.0.1:8761][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
15:52:18.126  INFO [DiscoveryClient-HeartbeatExecutor-0]    com.netflix.discovery.DiscoveryClient : DiscoveryClient_MSG-GW-CORE/msg-gw-core-01 - Re-registering apps/MSG-GW-CORE
15:52:18.126  INFO [DiscoveryClient-HeartbeatExecutor-0]    com.netflix.discovery.DiscoveryClient : DiscoveryClient_MSG-GW-CORE/msg-gw-core-01: registering service...
15:52:18.128 DEBUG [DiscoveryClient-HeartbeatExecutor-0]  o.a.h.client.protocol.RequestAddCookies : CookieSpec selected: default

So fix should be somewhere at server or client should not read response body if it receives 404. Is there any known workaround / configuration change for this?

Comment From: ztomic

My current workaround is using ErrorController at discovery server:

@RestController
static class CustomErrorController implements ErrorController {

    private static final String ERROR_MAPPING = "/error";

    @RequestMapping(ERROR_MAPPING)
    public ResponseEntity<Void> error() {
        return ResponseEntity.notFound().build();
    }

}

It is now returning empty 404 to client.

09:33:28.606 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 >> "PUT /eureka/apps/MSG-GW-CORE/msg-gw-core-01?status=UP&lastDirtyTimestamp=1670315518188 HTTP/1.1[\r][\n]"
09:33:28.606 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 >> "Accept: application/json, application/*+json[\r][\n]"
09:33:28.606 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 >> "Accept-Encoding: gzip, x-gzip, deflate[\r][\n]"
09:33:28.606 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 >> "Content-Length: 0[\r][\n]"
09:33:28.606 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 >> "Host: 127.0.0.1:8761[\r][\n]"
09:33:28.606 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 >> "Connection: keep-alive[\r][\n]"
09:33:28.606 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 >> "User-Agent: Apache-HttpClient/5.1.4 (Java/17.0.5)[\r][\n]"
09:33:28.606 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 >> "[\r][\n]"
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 << "HTTP/1.1 404 [\r][\n]"
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 << "Content-Length: 0[\r][\n]"
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 << "Date: Tue, 06 Dec 2022 08:33:28 GMT[\r][\n]"
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 << "Keep-Alive: timeout=60[\r][\n]"
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 << "Connection: keep-alive[\r][\n]"
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]          org.apache.hc.client5.http.wire : http-outgoing-69 << "[\r][\n]"
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-69 << HTTP/1.1 404 
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-69 << Content-Length: 0
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-69 << Date: Tue, 06 Dec 2022 08:33:28 GMT
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-69 << Keep-Alive: timeout=60
09:33:28.720 DEBUG [DiscoveryClient-HeartbeatExecutor-0]       org.apache.hc.client5.http.headers : http-outgoing-69 << Connection: keep-alive

Comment From: cmtjk

I can confirm this issue. We're currently migrating to Spring Boot 3.0.0 and our services (most still 2.7.x) are not able to properly register at our discovery server (3.0.0) but both eureka client and eureka server with Spring Boot 3.0.0 suffer from this issue.

We are currently applying @ztomic's workaround (Thanks 🎉!).

Comment From: cmtjk

Well, the response body of the server is not empty. It contains the default Spring (Boot) response body for 404 instead of an empty body:

2022-12-22 09_55_11-Evaluate

So the body is not mappable to com.netflix.appinfo.InstanceInfo in 1.

This also explains why @ztomic's workaround works, since he overrides the default error mapping for /error and returns an empty body.

So spring-cloud-netflix-eureka-server seems to have an issue where the empty 404 response in 2 is redirected to /error and the default 404 response body of Spring (Boot) is returned.

Comment From: cmtjk

You can run the following test for spring-cloud-netflix-eureka-server which passes in v3.1.4 but fails in v4.0.0 because the response body is not empty as expected by the client 12 if the client is not known to the server.

@Test
void testHeartbeat_ifServiceIsUnknown() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Accept", "application/json, application/*+json");
    ResponseEntity<String> resp = new TestRestTemplate()
            .exchange("http://localhost:" + this.port + "/servlet/eureka/apps/MSG-GW-CORE/msg-gw-core-01?status=UP&lastDirtyTimestamp=1670248378143",
                    HttpMethod.PUT,
                    new HttpEntity<>(headers),
                    String.class);
    assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
    assertThat(resp.getBody()).isNull();
}

Comment From: wizaord

Hello I've got the same issue. The workaround works. Do you plan to fix this issue in the next release ? Do you have a date ?

Comment From: GilbertHG

I have the same issue


  1. https://github.com/spring-cloud/spring-cloud-netflix/blob/v4.0.0/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/RestTemplateEurekaHttpClient.java#L99 

  2. https://github.com/spring-cloud/spring-cloud-netflix/blob/v4.0.0/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/http/WebClientEurekaHttpClient.java#L81