Example:

import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import java.time.Duration

@RestController
class Controller {
    @GetMapping
    fun test(): String {
        Thread.sleep(200)
        return "hello world"
    }
}

fun main() {
    requestWithTimeout(Duration.ofMillis(500))      //no timeout, as expected
    requestWithTimeout(Duration.ofMillis(1))        //timeout, as expected
    requestWithTimeout(Duration.ofNanos(1_000_000)) //timeout, as expected
    requestWithTimeout(Duration.ofNanos(999_999))   //no timeout, but expected
    requestWithTimeout(Duration.ZERO)
}

fun requestWithTimeout(duration: Duration) = println("$duration -> ${request(duration)}")

private fun request(duration: Duration): String? {
    return try {
        RestTemplateBuilder()
                .setReadTimeout(duration)
                .build()
                .getForEntity("http://127.0.0.1:8080", String::class.java)
                .body
    } catch (e: Exception) {
        e.message
    }
}

Result:

PT0.5S -> hello world
PT0.001S -> I/O error on GET request for "http://127.0.0.1:8080": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
PT0.001S -> I/O error on GET request for "http://127.0.0.1:8080": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
PT0.000999999S -> hello world
PT0S -> hello world

I think problem is here: RestTemplateBuilder.setReadTimeout. Spring Boot version: 2.3.4.RELEASE

Comment From: wilkinsona

Thanks for the report. The read timeout has millisecond precision so I don't think there's anything we can do to change the behaviour here. Furthermore, Duration.ofNanos(999_999).toMillis() returns 0. What do you expect the millisecond timeout to be when you set it to a value less than a millisecond?

Comment From: Potat0x

Furthermore, Duration.ofNanos(999_999).toMillis() returns 0. What do you expect the millisecond timeout to be when you set it to a value less than a millisecond?

Thats why I pasted link to this function :)

Thanks for the report. The read timeout has millisecond precision so I don't think there's anything we can do to change the behaviour here.

You mean precision of underlying libraries?

Comment From: wilkinsona

Thats why I pasted link to this function :)

I had assumed as much, but that doesn't answer my question which was the following:

What do you expect the millisecond timeout to be when you set it to a value less than a millisecond?

You mean precision of underlying libraries?

Yes.

Comment From: Potat0x

I had assumed as much, but that doesn't answer my question which was the following:

What do you expect the millisecond timeout to be when you set it to a value less than a millisecond?

0? But there is also toNanos. Anyway, it doesnt matter if underlying library use millisecond precision.