Bundle stats upload fails against AWS S3 storage (chunked Transfer-Encoding → 501 NotImplemented)
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 82/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 静か
- 技術スタック
- aws, node.js, typescript
- 領域
- cloud
調査の方向性
packages/bundler-plugin-core/src/utils/uploadStats.ts から始め、stats payload がどのように構築され、fetchWithRetry に渡されるかを確認してください。Upload が既知の長さの body を使用していることを検証し、実際の AWS S3 に対して plugin をテストしてください。chunked-transfer の 501 エラーを返すのではなく、bundle stats の upload が成功すれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Summary
uploadStats sends the stats payload as a streamed request body (ReadableStream + duplex: "half"), which undici serializes with Transfer-Encoding: chunked (no Content-Length). Amazon S3 does not support chunked PUTs and rejects the pre-signed upload with 501 NotImplemented, so bundle analysis is completely non-functional on any self-hosted Codecov instance whose storage backend is real AWS S3.
MinIO (the common self-hosted default) is lenient and accepts chunked, which is likely why this hasn't surfaced widely — but a Codecov Enterprise instance configured with services.minio.host: s3.amazonaws.com hits it every time.
Environment
@codecov/vite-plugin2.0.1 (@codecov/bundler-plugin-core2.0.1)- Node.js v24.14.1
- Self-hosted Codecov (Enterprise
25.5.1) with storage backend = AWS S3 (services.minio.host: s3.amazonaws.com)
Root cause
In packages/bundler-plugin-core/src/utils/uploadStats.ts the body is a stream:
const stream = new ReadableStream({
pull(controller) { /* ... enqueue chars ... */ },
}).pipeThrough(new TextEncoderStream());
await fetchWithRetry({
url: preSignedUrl,
requestData: {
method: "PUT",
headers: { "Content-Type": "application/json" },
duplex: "half",
body: stream, // <-- undici sends Transfer-Encoding: chunked, no Content-Length
},
});
A streamed body with no known length is sent as Transfer-Encoding: chunked. S3 returns:
<Error>
<Code>NotImplemented</Code>
<Message>A header you provided implies functionality that is not implemented</Message>
<Header>Transfer-Encoding</Header>
</Error>
With a large real payload, S3 responds 501 and closes the socket mid-upload, so undici surfaces it as a low-level TypeError: fetch failed (rethrown from fetchWithRetry) rather than the clean 501 — hence the opaque Failed to upload stats, fetch failed users see. With a tiny payload the full body flushes first and you get the clean 501.
Reproduction
- Configure a self-hosted Codecov whose storage is genuine AWS S3.
- Run any build with the plugin enabled +
CODECOV_TOKENset, pointingapiUrlat that instance. - Pre-signed URL fetch succeeds;
upload-statsfails 3× →Failed to upload stats, fetch failed.
Minimal repro of the underlying HTTP behavior (Node fetch → S3 pre-signed PUT):
// buffered string body -> Content-Length set -> 200 OK
await fetch(preSignedUrl, { method: "PUT", headers: { "Content-Type": "application/json" }, body: statsJson })
// streamed body + duplex:"half" -> Transfer-Encoding: chunked -> 501 NotImplemented
const stream = new ReadableStream({ /* enqueue chars */ }).pipeThrough(new TextEncoderStream())
await fetch(preSignedUrl, { method: "PUT", headers: { "Content-Type": "application/json" }, duplex: "half", body: stream })
Suggested fix
Send the payload as a buffered string/Uint8Array so fetch sets Content-Length, instead of a ReadableStream:
await fetchWithRetry({
url: preSignedUrl,
requestData: {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: message, // string -> Content-Length, S3-compatible
},
});
The stats JSON is already fully in memory (it's iterated char-by-char to build the stream), so buffering it adds no meaningful memory overhead and makes uploads compatible with S3 as well as MinIO/GCS.
Alternatively, keep streaming but compute and set an explicit Content-Length header, or use S3's aws-chunked content-encoding — but a plain buffered body is by far the simplest and works across all backends.
I've verified the buffered-body change fixes uploads against AWS S3 end-to-end (Successfully uploaded stats). Happy to open a PR if useful.
- 主要言語
- TypeScript
- スター
- 9
- フォーク
- 10
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
codecov/codecov-javascript-bundler-plugins のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 63/100
-
難易度 3/5 1〜2日 初心者へのやさしさ 52/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
-
Support vite v7オープン
難易度 3/5 1〜2日 初心者へのやさしさ 58/100
codecov/codecov-javascript-bundler-plugins#264 · コメント 9 件 · リアクション 37 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 45/100
codecov/codecov-javascript-bundler-plugins の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 77/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
cline/mcp-marketplace#2932 ·
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
難易度 1/5 1時間未満 初心者へのやさしさ 82/100
lingdojo/kana-dojo#32188 · コメント 1 件 · リアクション 5 件 ·
メンテナーはふだん 1 日以内に返信
-
triage
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
Portkey-AI/gateway#1844 ·
メンテナーはふだん 1 日以内に返信
-
needs triage
難易度 2/5 1〜3時間 初心者へのやさしさ 61/100
rjsf-team/react-jsonschema-form#5495 ·
メンテナーはふだん 2 日以内に返信