Skip to content

fix(amazonq): stream large ATX artifact downloads to disk - #2885

Open
xueningl-az wants to merge 2 commits into
Amazon-Q-Developer:mainfrom
xueningl-az:fix/atx-large-artifact-download-timeout
Open

xueningl-az wants to merge 2 commits into
Amazon-Q-Developer:mainfrom
xueningl-az:fix/atx-large-artifact-download-timeout

Conversation

@xueningl-az

Copy link
Copy Markdown
Contributor

Problem

Ticket V2381716118 — a customer (United Airlines, VS2026) could not download a
large Transformation_Report.html from the Artifact Explorer. In the LSP
logs, CreateArtifactDownloadUrl succeeds every time, yet the file never
lands and no error surfaces.

Root cause is in downloadArtifactToPath:

const response = await got.get(url, { responseType: 'buffer', timeout: {
request: 30000 } })
fs.writeFileSync(filePath, Buffer.from(response.body))
- timeout: { request: 30000 } caps the entire request, including body
  transfer. A large report that takes >30s to download aborts with a
  TimeoutError.
- The error is swallowed by the catch and returned only as a generic { 
  Success: false }, so the user sees a silent failure.
- responseType: 'buffer' also buffers the whole file (plus a copy) in memory.

Fix

- Stream the presigned URL straight to disk with got.stream + stream/promises
  pipeline — no full-file in-memory buffering.
- Replace the whole-request timeout with inactivity-based timeouts (response
  30s to headers, socket 60s idle) so a large-but-healthy download is no
  longer capped by wall-clock time.
- Add success/error logging (bytes transferred, failure reason) for
  diagnosability.

Testing

- Added 3 unit tests for downloadArtifactToPath (large-file streaming success,
  mid-stream failure surfaces the error, existing URL-failure branch).
- npm run test:unit for aws-lsp-codewhisperer: 297 passing, 0 failing.
- ESLint/Prettier clean on the changed files.

downloadArtifactToPath buffered the whole artifact into memory via
got.get(responseType:'buffer') under timeout:{request:30000}. The
'request' timeout caps the ENTIRE request including body transfer, so a
large artifact (e.g. Transformation_Report.html) that takes >30s to
download aborts with a TimeoutError. That error was swallowed by the
catch and surfaced only as a generic download failure — matching the
customer report where CreateArtifactDownloadUrl succeeds but the report
never downloads (V2381716118).

Stream the presigned URL straight to disk with got.stream + pipeline,
and switch to inactivity-based timeouts (response 30s to headers, socket
60s idle) so a large-but-healthy download is no longer capped by wall
clock, and no longer double-buffered in memory. Add success/error
logging for diagnosability.
@xueningl-az
xueningl-az requested a review from a team as a code owner September 25, 2026 02:22
Every failure branch now logs clearly: the previously-silent missing-URL
branch logs an error, and the catch records the got error code, timeout
phase, HTTP status, bytes transferred before failure, and full stack.
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 2.43902% with 40 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...anguage-server/netTransform/atxTransformHandler.ts 2.43% 40 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants