Bun 1.4.3 EAI_AGAIN vs ETIMEOUT: retry a Sume submit safely

Bun 1.4.3 reports a temporary DNS failure as EAI_AGAIN, not ETIMEOUT. Update your retry check, and keep one Idempotency-Key across every Sume submit retry.

4 min readSume
All posts

If your Bun retry loop matches ETIMEOUT to detect a flaky network, Bun 1.4.3 (released October 10, 2026) stops matching it for temporary DNS failures: they now surface as EAI_AGAIN. Add EAI_AGAIN to the retryable set, and send the same Idempotency-Key on every attempt of a Sume submit, so a retry that did reach the API does not start a second billed job.

The Bun release notes list the fix under their retry items: temporary DNS failures reported ETIMEOUT instead of EAI_AGAIN, which broke retry logic (Bun v1.4.3 release notes, read 2026-10-13). The same notes list a retry fix for HTTP/3 when a QUIC connection closed before the response headers arrived. Sume's side of the contract is in Errors and credits.

What changed in Bun 1.4.3

Only the error code changed. A request that fails to resolve api.sume.com before any byte leaves your machine used to look like a timeout, and now looks like a name-resolution retry hint. Code that did if (err.code === "ETIMEOUT") retry() silently stopped retrying DNS blips after the upgrade.

Bun 1.4.3 fetch and retry items (Bun release notes, read 2026-10-13)
Item in the notesWhat it means for a Sume caller
Temporary DNS failure reports EAI_AGAIN instead of ETIMEOUTMatch EAI_AGAIN in your retry check
HTTP/3 automatic retry when QUIC closes before response headersA retry can happen below your code; keep the key stable
fetch rejects when Content-Length does not match the bodySend JSON as a string or bytes you measured, not a hand-set length

Why the key must outlive the retry

A DNS failure means the request never left, so retrying is safe. A timeout or a reset after the body was sent is different: the API may have accepted the job. Sume's docs say to back off on 429, to use retry-after when present, and not to retry unsafe submit requests without an Idempotency-Key. A 503 such as provider_capacity_exceeded says to retry later with the same key.

That makes one rule for the loop: generate the key once per intended job, outside the loop, and reuse it for each attempt. A fresh key per attempt turns every ambiguous failure into a possible duplicate.

A retry loop that fits 1.4.3

This sketch retries name-resolution failures and timeouts a few times with growing waits, and passes the same key every time. It uses the job's own status later, so read Jobs and results for the poll step.

const KEY = crypto.randomUUID(); // once per intended job
const RETRY = new Set(["EAI_AGAIN", "ETIMEOUT", "ECONNRESET"]);

async function submit(body: object) {
  for (let attempt = 0; attempt < 4; attempt++) {
    try {
      const res = await fetch("https://api.sume.com/v1/videos", {
        method: "POST",
        headers: {
          authorization: `Bearer ${process.env.SUME_API_KEY}`,
          "content-type": "application/json",
          "idempotency-key": KEY,
        },
        body: JSON.stringify(body),
        signal: AbortSignal.timeout(30_000),
      });
      if (res.status === 429 || res.status === 503) {
        const wait = Number(res.headers.get("retry-after") ?? 2 ** attempt);
        await Bun.sleep(wait * 1000);
        continue;
      }
      return res;
    } catch (err: any) {
      if (!RETRY.has(err?.code) && err?.name !== "TimeoutError") throw err;
      await Bun.sleep(2 ** attempt * 1000);
    }
  }
  throw new Error("submit failed after 4 attempts");
}

What to check after upgrading

Grep your retry helpers for the string ETIMEOUT. Where the code classifies errors by code, add EAI_AGAIN. Where it relies on the Sume SDK instead, note that the SDK lets you supply your own fetch, so retries you wrap around it are your responsibility and the same key rule applies.

  • Keep the key outside the retry loop and tie it to your own record id.
  • Treat EAI_AGAIN as retryable; do not retry 4xx validation errors.
  • Honor retry-after on 429 before the next attempt.
  • After an ambiguous failure, a retry with the same key is the safe move.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume