Java HttpClient timeout: no default, so set two of them
Java's HttpClient has no request timeout unless you set one: connectTimeout on the client, timeout on each request, and HttpTimeoutException.

The Java HttpClient (java.net.http, since Java 11) has no request timeout by default: the javadoc says not setting one is the same as an infinite duration, so send blocks forever if no response comes. Set two timeouts: HttpClient.Builder.connectTimeout(Duration) for opening a connection, and HttpRequest.Builder.timeout(Duration) for each request's response. When one expires, send throws HttpTimeoutException, or HttpConnectTimeoutException for the connect phase.
Java facts come from the Java SE 21 javadoc for HttpClient, HttpClient.Builder, HttpRequest.Builder and HttpTimeoutException. The slow-API example is Sume's, from Jobs and results and Video Generation, all read on 2026-09-29.
What are the Java HttpClient timeout settings?
There are two, set in two places, and HttpClient.newHttpClient() sets neither.
| Setting | Covers | If not set | On expiry |
|---|---|---|---|
HttpClient.Builder.connectTimeout(Duration) | Establishing a new connection; no effect when a connection is reused | connectTimeout() returns an empty Optional | HttpConnectTimeoutException |
HttpRequest.Builder.timeout(Duration) | Receiving the response to this request | Same as an infinite duration: block forever | HttpTimeoutException |
How do I set a timeout on a Java HttpClient request?
Put connectTimeout on the client you reuse and timeout on each request. A non-positive duration makes timeout throw IllegalArgumentException. HttpConnectTimeoutException extends HttpTimeoutException, which extends IOException, so catch the narrower one first. With sendAsync, the future completes exceptionally with the same exceptions instead.
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10)) // new connections only
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.sume.com/v1/videos"))
.timeout(Duration.ofSeconds(30)) // this request's response
.header("Authorization", "Bearer " + System.getenv("SUME_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", "order-8823-clip-v1")
.POST(HttpRequest.BodyPublishers.ofString(
"{\"model\":\"sume/auto\",\"prompt\":\"A product clip on a desk\",\"aspect_ratio\":\"9:16\",\"duration\":5}"))
.build();
try {
HttpResponse<String> res = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(res.statusCode() + " " + res.body()); // 202: id, polling_url
} catch (HttpConnectTimeoutException e) {
// no connection within 10 s: retry with the same Idempotency-Key
} catch (HttpTimeoutException e) {
// no response within 30 s: the job may exist; retry with the same key
}How long should the timeout be for a slow API?
Short, because an async job API answers before the work is done. Sume's video create returns a job id and polling URL immediately, and you poll GET /v1/videos/{jobId} until the status is completed. Where a Sume submit endpoint offers the blocking sync mode, it waits at most 30 seconds and then returns the job, so no create call needs a request timeout measured in minutes. Put the long deadline in your polling loop instead: Sume's jobs guide calls 20 minutes reasonable for video, and says that deadline is client-side.
Give each status poll the same short per-request timeout, and treat an HttpTimeoutException on a poll as one missed read, not a failed job: wait with exponential backoff and poll again, and stop only when the status is terminal. The connect timeout matters less here, because it has no effect when the client reuses an open connection.
What happens to the job when HttpClient times out?
It keeps running. A client-side timeout does not cancel the job; it keeps running and still bills. Keep the job id and pick it back up from the status URL, and don't resubmit the paid request because a local process timed out. If the create timed out before you saw an id, resend it with the same Idempotency-Key, and the retry returns the original job instead of billing a second one. Spring Retry for paid API calls wraps that retry, and text to speech API in Java shows a full submit-and-poll loop.
Sources
- Java SE 21: HttpClient (read 2026-09-29)
- Java SE 21: HttpClient.Builder (read 2026-09-29)
- Java SE 21: HttpRequest.Builder (read 2026-09-29)
- Java SE 21: HttpTimeoutException (read 2026-09-29)
- Java SE 21: HttpConnectTimeoutException (read 2026-09-29)
- Java SE 21: HttpRequest.BodyPublishers (read 2026-09-29)
- Jobs and results
- Video Generation
Related posts
More in Developers
- JSON to video API: render an MP4 from a timeline document
A JSON to video API renders one MP4 from a document that says which clips play when, over which audio. How Sume's Timeline 1.0 does it, and costs.
- Kling API rate limit: concurrency by package and error 1303
Kling's API limits concurrent tasks by resource package, not requests per second. Over the cap, a create fails with HTTP 429, code 1303.
- Promise.allSettled vs Promise.all for a batch of API jobs
Promise.allSettled waits for every promise and reports each outcome; Promise.all rejects on the first failure. For paid API jobs, use allSettled.
- Python API rate limiting: stay under a per-minute limit
Pace Python API calls with an asyncio limiter set under the API's per-minute budget, keep polling on its own budget, and back off on 429 retry-after.
Written by Sume