Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Request timeout does not cover stalled response bodies

Open
#206 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
74/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
typescript
Domain
api

Research direction

Start in src/core.ts:564-568 to trace where fetchWithTimeout clears its timer, then read defaultParseResponse() in src/core.ts:70-91 and the timeout contract in README.md:135-154 and src/index.ts:62-69. Run the supplied stalled-response reproduction and verify that the request rejects with APIConnectionTimeoutError around the configured timeout instead of remaining pending.

Written by the indexing model from the issue text.

Description

Description

The documented request timeout only lasts until fetch() resolves with response headers; it does not cover reading/parsing the response body.

fetchWithTimeout() clears its timer in src/core.ts:564-568 as soon as the fetch promise settles. defaultParseResponse() reads response.json()/response.text() later (src/core.ts:70-91) with no active timer. A server that sends headers and then stalls can therefore leave the SDK promise pending indefinitely, despite README.md stating that requests time out and throw APIConnectionTimeoutError.

Reproduction
import http from 'node:http';
import Browserbase from '@browserbasehq/sdk';

const server = http.createServer((_req, res) => {
  res.writeHead(200, { 'content-type': 'application/json' });
  res.write('{'); // send headers and a partial body, then stall
});
await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve));

const address = server.address();
if (!address || typeof address === 'string') throw new Error('missing port');

const client = new Browserbase({
  apiKey: 'test',
  baseURL: `http://127.0.0.1:${address.port}`,
  timeout: 50,
  maxRetries: 0,
});

const result = await Promise.race([
  client.get('/stall').then(
    () => 'resolved',
    (error) => error.constructor.name,
  ),
  new Promise<string>((resolve) => setTimeout(() => resolve('still pending'), 250)),
]);

console.log(result); // still pending, not APIConnectionTimeoutError
server.closeAllConnections();
server.close();
Expected behavior

The request rejects with APIConnectionTimeoutError around 50 ms, including time spent receiving/parsing the body.

Actual behavior

The request remains pending after 250 ms and can hang indefinitely.

Why this matters

A partial or slow response defeats the SDK's primary bound on request duration. This can exhaust application concurrency and contradicts the timeout contract documented in README.md:135-154 and ClientOptions in src/index.ts:62-69.

Tested with Node 22.14.0 against @browserbasehq/sdk 2.18.0 / current main (b781bd7).

Dominant language
TypeScript
Stars
64
Forks
17
Avg merge
13m
Merged PRs (30d)
4

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from browserbase/sdk-node

All issues in browserbase/sdk-node

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.