SDK for JavaScriptで発生したInvalidChunkSizeErrorを解消する
はじめに
Dockerのversionを18から20にアップグレードしたところ、SDK for JavaScript v3でS3へアップロードする際に、InvalidChunkSizeError
のエラーが発生したため、その解消方法について記事にしていきます。
InvalidChunkSizeError: Only the last chunk is allowed to have a size less than 8192 bytes
Only the last chunk is allowed to have a size less than 8192 bytes
バージョンは以下の通りです。
ライブラリ・言語 | バージョン |
---|---|
aws-sdk/client-s3 | v3.45.0 |
aws-sdk/lib-storage | v3.45.0 |
aws-sdk | v2.1048.0 |
node | v20.11.0 |
typescript | v4.4.4 |
InvalidChunkSizeErrorについて
これはAWS SDK(@aws-sdk/client-s3)でS3へのストリームアップロード処理中にチャンクサイズのルールを破ったことに起因します。AWS S3では、マルチパートアップロード(単一のオブジェクトを複数に分割してアップロードできる機能)やストリームアップロードを行う際に以下のようなルールがあり、処理中に8192バイト未満のチャンクが途中で送られてしまったことでこのエラーが発生したことが推測されます。
- 各チャンクは8192バイト(8KB)以上でなければならない
- 最後のチャンクだけは8KB未満でも大丈夫(
Only the last chunk is allowed to have a size less than 8192 bytes
で8192バイト未満であることが許可されることが示されています。最後のチャンクのみ「残りのデータが少ない場合に限り」小さくても受け入れることで、無駄な空チャンクの送信を回避しています。)
チャンクサイズとは、ファイルアップロードやダウンロード時に一度に転送されるデータのサイズ(チャンク)に関する制限のことを指します。
解消方法
S3Client.send(PutObjectCommand)
を使用している箇所を@aws-sdk/lib-storageのStream Upload
に書き換えます。
this.destinationS3.send(
new PutObjectCommand({
Bucket: process.env.SOURCE_BUCKET,
Key: 'some/key/file.jpg',
Body: someStreamOrBuffer,
ContentType: this.excelContentType,
})
import { Upload } from '@aws-sdk/lib-storage';
await new Upload({
client: s3Client,
params: {
Bucket: process.env.SOURCE_BUCKET,
Key: 'some/key/file.jpg',
Body: someStreamOrBuffer,
ContentType: this.excelContentType,
},
}).done();
Upload
を使用することでチャンクサイズなど内部的によしなに最適化されて処理されます。
requestChecksumCalculationが発生した場合
TypeError: this.client.config.requestChecksumCalculation is not a function
lib-storage
がS3クライアントに存在するべきrequestChecksumCalculation
オプションを期待しているのに、その関数が存在しないために発生しているエラーとなります。lib-storage側が内部的に使っているミドルウェア(flexible-checksums)の一部であり、古いAWS SDKとlib-storage
の組み合わせがズレると問題になります。
AWS SDKのversionを最新に設定するか、両方のVersionを揃えることでエラーが解消します。
"dependencies": {
"@aws-sdk/client-s3": "^3.45.0",
"@aws-sdk/lib-storage": "^3.45.0"
}
最後に
今回は、InvalidChunkSizeErrorの解消について記事にしました。
ここまで読んでいただきありがとうござました。
Discussion