Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Response body read errors bypass the SDK's typed error handling

オープン
#757 コメント 0 件 リアクション 0 件 担当者 1 名 GitHub で見る

@radenkovic がすでに取り組んでいます。

2026年7月28日 から。

評価

この issue はまだ評価されていません。

説明

Describe the bug

When the HTTP connection drops while the SDK is reading a response body, the error that reaches my code is a raw TypeError: terminated from Node's fetch stack, not one of the SDK's own error types (NylasApiError, NylasOAuthError, NylasSdkTimeoutError). My catch block checks instanceof NylasApiError, so it falls through and I lose the request context I normally rely on (the requestId and flow id).

Looking at src/apiClient.ts, the two response-body reads are outside any try/catch:

  • requestWithResponse reads the body at line 317: const text = await response.text();. The try block starts on the next line and only wraps JSON.parse(text), so a failure in response.text() itself is not caught here.
  • requestRaw reads the body at line 348: const arrayBuffer = await response.arrayBuffer();, with no try/catch in the function.

This looks inconsistent with sendRequest, which already wraps fetch() and converts failures into SDK errors (for example AbortError becomes NylasSdkTimeoutError, and a non-2xx status becomes NylasApiError). A connection that fails before the first byte surfaces a typed error, but the same connection failing mid-body surfaces a raw undici error. The requestRaw path is the one I hit most, since it backs Attachments.download() and large downloads over a flaky network are the most likely to be cut off partway.

To Reproduce

Point the client at a local server that returns a success status and then closes the socket mid-body, so the body read rejects:

const http = require('http');
const Nylas = require('nylas').default;

// Server that sends headers + a partial body, then destroys the socket
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.write('{"request_id":"abc","data":');   // intentionally incomplete
  res.socket.destroy();                        // drop the connection mid-body
});

server.listen(0, async () => {
  const nylas = new Nylas({ apiKey: 'test', apiUri: `http://localhost:${server.address().port}` });

  try {
    await nylas.messages.list({ identifier: 'me' });
  } catch (e) {
    console.log('name:', e.name);                 // TypeError
    console.log('message:', e.message);           // terminated
    console.log('is NylasApiError:', e instanceof Nylas.NylasApiError); // false
  } finally {
    server.close();
  }
});

The same happens through nylas.attachments.download(...), which reads the body with response.arrayBuffer().

Expected behavior

A failure while reading the response body should be surfaced the same way as other transport failures: as an SDK error type, carrying the flow id / request id when available, so that a catch (e) { if (e instanceof NylasApiError) ... } block behaves consistently regardless of when in the request lifecycle the connection dropped. At minimum the raw error should be wrapped in a descriptive Error rather than leaking terminated.

SDK Version:

8.4.0

Additional context

The two spots are requestWithResponse (src/apiClient.ts:317) and requestRaw (src/apiClient.ts:348). Wrapping each body read in a try/catch and rethrowing an SDK-typed error, matching the pattern already used in sendRequest and in the existing JSON.parse catch, would keep the error surface consistent. Happy to open a PR with that change if it would be useful.

主要言語
TypeScript
スター
181
フォーク
126
平均マージ
4日 6時間
マージ済み PR(30日)
3

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

nylas/nylas-nodejs のほかの issue

nylas/nylas-nodejs の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。