n8n - 💡(How to fix) Fix AWS S3 V2 node `EntityTooSmall` error when `N8N_DEFAULT_BINARY_DATA_MODE=s3`

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

The error returned by S3: <Error> </Error>

Root Cause

AwsS3V2.node.ts uses a multipart upload whenever binaryPropertyData.id is set, requesting chunks of UPLOAD_CHUNK_SIZE = 5 MB:

// packages/nodes-base/nodes/Aws/S3/V2/AwsS3V2.node.ts
if (isBinaryData) {
	const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
	const binaryPropertyData = this.helpers.assertBinaryData(i, binaryPropertyName);
	let uploadData: Buffer | Readable;
	multipartHeaders['Content-Type'] = binaryPropertyData.mimeType;
	if (binaryPropertyData.id) {
		uploadData = await this.helpers.getBinaryStream(
			binaryPropertyData.id,
			UPLOAD_CHUNK_SIZE,
		);
		const createMultiPartUpload = await awsApiRequestREST.call(
			this,
			servicePath,
			'POST',
			`${path}?uploads`,
			body,
			qs,
			{ ...neededHeaders, ...multipartHeaders },
			{},
			region as string,
		);
            // ...
      }
}

BinaryDataService.getAsStream forwards the requested chunkSize to the active manager. Each manager handles it differently:

ManagerHonors chunkSize?Implementation
FileSystemManagerYescreateReadStream(filePath, { highWaterMark: chunkSize }) — small files emit one chunk
DatabaseManagerYesReadable.from(buffer) — emits the whole buffer as one chunk
ObjectStoreManagerNoReturns the raw AWS SDK HTTP response stream, which emits TCP-sized chunks

packages/core/src/binary-data/object-store.manager.ts:39

async getAsStream(fileId: string) {
	return await this.objectStoreService.get(fileId, { mode: 'stream' });
}

The chunkSize parameter is not even accepted, so the request is silently dropped. The returned stream emits chunks at whatever the TCP layer hands it — typically. For an 2 MB file this yields several parts all below S3's 5 MB minimum, so CompleteMultipartUpload fails with EntityTooSmall.

In filesystem and database modes the same workflow works because the manager emits the chunks following the minimum size file.

Fix Action

Workaround

Set N8N_DEFAULT_BINARY_DATA_MODE=filesystem (or database). In queue / scaling mode, a shared volume that all worker pods can read/write (e.g. EFS with ReadWriteMany) is required for filesystem mode.

Code Example

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>EntityTooSmall</Code>
  <Message>Your proposed upload is smaller than the minimum allowed size</Message>
  <ProposedSize>16384</ProposedSize>
  <MinSizeAllowed>5242880</MinSizeAllowed>
  <PartNumber>1</PartNumber>
</Error>

---

// packages/nodes-base/nodes/Aws/S3/V2/AwsS3V2.node.ts
if (isBinaryData) {
	const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
	const binaryPropertyData = this.helpers.assertBinaryData(i, binaryPropertyName);
	let uploadData: Buffer | Readable;
	multipartHeaders['Content-Type'] = binaryPropertyData.mimeType;
	if (binaryPropertyData.id) {
		uploadData = await this.helpers.getBinaryStream(
			binaryPropertyData.id,
			UPLOAD_CHUNK_SIZE,
		);
		const createMultiPartUpload = await awsApiRequestREST.call(
			this,
			servicePath,
			'POST',
			`${path}?uploads`,
			body,
			qs,
			{ ...neededHeaders, ...multipartHeaders },
			{},
			region as string,
		);
            // ...
      }
}

---

async getAsStream(fileId: string) {
	return await this.objectStoreService.get(fileId, { mode: 'stream' });
}

---

N8N_DEFAULT_BINARY_DATA_MODE=s3
   N8N_EXTERNAL_STORAGE_S3_BUCKET_NAME=<your-bucket>
   N8N_EXTERNAL_STORAGE_S3_HOST=s3.us-east-1.amazonaws.com
   N8N_EXTERNAL_STORAGE_S3_AUTH_AUTO_DETECT=true

---

// packages/core/src/binary-data/object-store.manager.ts
import { Transform } from 'node:stream';

async getAsStream(fileId: string, chunkSize?: number) {
    const source = await this.objectStoreService.get(fileId, { mode: 'stream' });

    if (!chunkSize) return source;

    let buffered = Buffer.alloc(0);
    const rechunker = new Transform({
        transform(chunk: Buffer, _encoding, callback) {
            buffered = Buffer.concat([buffered, chunk]);
            while (buffered.length >= chunkSize) {
                this.push(buffered.subarray(0, chunkSize));
                buffered = buffered.subarray(chunkSize);
            }
            callback();
        },
        flush(callback) {
            if (buffered.length > 0) this.push(buffered);
            callback();
        },
    });

    return source.pipe(rechunker);
}

---

debug   Sending PUT request to S3 { "Bucket": "<n8n-bucket>", "Key": "workflows/.../binary_data/<uuid>", "ContentLength": 64, ... }
debug   Sending GET request to S3 { "bucket": "<n8n-bucket>", "key": "workflows/.../binary_data/<uuid>" }
EMA: chunk 64 < 5242880          ← single TCP-sized chunk (file fits in one frame)
debug   Running node "Upload a file1" finished successfully
RAW_BUFFERClick to expand / collapse

Bug Description

When n8n is configured with N8N_DEFAULT_BINARY_DATA_MODE=s3 (we have a licence as Bancolombia S.A), uploading binary files via the AWS S3 V2 node (Object → Upload, binary data enabled) fails with EntityTooSmall for any file larger than ~40 KB. The same workflow succeeds when N8N_DEFAULT_BINARY_DATA_MODE is set to filesystem or database.

The error returned by S3:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>EntityTooSmall</Code>
  <Message>Your proposed upload is smaller than the minimum allowed size</Message>
  <ProposedSize>16384</ProposedSize>
  <MinSizeAllowed>5242880</MinSizeAllowed>
  <PartNumber>1</PartNumber>
</Error>

Root cause

AwsS3V2.node.ts uses a multipart upload whenever binaryPropertyData.id is set, requesting chunks of UPLOAD_CHUNK_SIZE = 5 MB:

// packages/nodes-base/nodes/Aws/S3/V2/AwsS3V2.node.ts
if (isBinaryData) {
	const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
	const binaryPropertyData = this.helpers.assertBinaryData(i, binaryPropertyName);
	let uploadData: Buffer | Readable;
	multipartHeaders['Content-Type'] = binaryPropertyData.mimeType;
	if (binaryPropertyData.id) {
		uploadData = await this.helpers.getBinaryStream(
			binaryPropertyData.id,
			UPLOAD_CHUNK_SIZE,
		);
		const createMultiPartUpload = await awsApiRequestREST.call(
			this,
			servicePath,
			'POST',
			`${path}?uploads`,
			body,
			qs,
			{ ...neededHeaders, ...multipartHeaders },
			{},
			region as string,
		);
            // ...
      }
}

BinaryDataService.getAsStream forwards the requested chunkSize to the active manager. Each manager handles it differently:

ManagerHonors chunkSize?Implementation
FileSystemManagerYescreateReadStream(filePath, { highWaterMark: chunkSize }) — small files emit one chunk
DatabaseManagerYesReadable.from(buffer) — emits the whole buffer as one chunk
ObjectStoreManagerNoReturns the raw AWS SDK HTTP response stream, which emits TCP-sized chunks

packages/core/src/binary-data/object-store.manager.ts:39

async getAsStream(fileId: string) {
	return await this.objectStoreService.get(fileId, { mode: 'stream' });
}

The chunkSize parameter is not even accepted, so the request is silently dropped. The returned stream emits chunks at whatever the TCP layer hands it — typically. For an 2 MB file this yields several parts all below S3's 5 MB minimum, so CompleteMultipartUpload fails with EntityTooSmall.

In filesystem and database modes the same workflow works because the manager emits the chunks following the minimum size file.

To Reproduce

  1. Run n8n with the following environment variables:
    N8N_DEFAULT_BINARY_DATA_MODE=s3
    N8N_EXTERNAL_STORAGE_S3_BUCKET_NAME=<your-bucket>
    N8N_EXTERNAL_STORAGE_S3_HOST=s3.us-east-1.amazonaws.com
    N8N_EXTERNAL_STORAGE_S3_AUTH_AUTO_DETECT=true
  2. Confirm n8n logs show EMA: se configuró el s3 / S3 manager registered (i.e. binary data is actually being stored in S3).
  3. Create a workflow with two nodes:
    • Form trigger (or any node that produces binary data, e.g. HTTP Request returning a file)
    • AWS S3 V2 → Object → Upload, with Binary Data enabled and pointing at the previous node's binary property.
  4. Trigger the workflow with a file ≥ ~17 KB and < 5 MB (e.g. an 85 KB PDF).
  5. The AWS S3 V2 node fails with EntityTooSmall.

A 64-byte file does not reproduce the issue: the entire HTTP response from the internal S3 GET fits in a single TCP frame, producing one multipart part, which is the last part and therefore exempt from the 5 MB minimum.

Switching N8N_DEFAULT_BINARY_DATA_MODE to filesystem (or database) and re-running the same workflow with the same file makes the upload succeed.

Expected behavior

The AWS S3 V2 node should successfully upload binary files of any size regardless of the value of N8N_DEFAULT_BINARY_DATA_MODE. Specifically, when binary data is stored in s3 mode, the multipart upload performed by the node must produce parts that respect S3's minimum part size (5 MB for non-last parts), as it does correctly in filesystem and database modes.

Suggested fix

Make ObjectStoreManager.getAsStream honor chunkSize the same way FileSystemManager does, but without buffering the entire object in memory (since s3 mode has no upper bound on file size). A streaming Transform that re-chunks on the fly:

// packages/core/src/binary-data/object-store.manager.ts
import { Transform } from 'node:stream';

async getAsStream(fileId: string, chunkSize?: number) {
    const source = await this.objectStoreService.get(fileId, { mode: 'stream' });

    if (!chunkSize) return source;

    let buffered = Buffer.alloc(0);
    const rechunker = new Transform({
        transform(chunk: Buffer, _encoding, callback) {
            buffered = Buffer.concat([buffered, chunk]);
            while (buffered.length >= chunkSize) {
                this.push(buffered.subarray(0, chunkSize));
                buffered = buffered.subarray(chunkSize);
            }
            callback();
        },
        flush(callback) {
            if (buffered.length > 0) this.push(buffered);
            callback();
        },
    });

    return source.pipe(rechunker);
}

Memory footprint with this approach is bounded by chunkSize (5 MB) regardless of the underlying object size.

Debug Info

n8n setup

  • n8n version: reproduced on 2.6.3 and 2.18.6 (the affected code is unchanged across this range)
  • Database: PostgreSQL
  • Execution mode: reproduced in both regular and queue modes
  • Running n8n via: Docker / Kubernetes (also reproducible locally with pnpm dev from the cloned repo)

Binary data / external storage

  • N8N_DEFAULT_BINARY_DATA_MODE=s3
  • N8N_EXTERNAL_STORAGE_S3_HOST=s3.us-east-1.amazonaws.com
  • N8N_EXTERNAL_STORAGE_S3_AUTH_AUTO_DETECT=true
  • AWS SDK version: @aws-sdk/[email protected]

Affected node

  • n8n-nodes-base.awsS3 (V2), operation Object → Upload, with binary data enabled

Relevant log excerpt (n8n 2.6.3, local repro with file < 17 KB ⇒ succeeds)

debug   Sending PUT request to S3 { "Bucket": "<n8n-bucket>", "Key": "workflows/.../binary_data/<uuid>", "ContentLength": 64, ... }
debug   Sending GET request to S3 { "bucket": "<n8n-bucket>", "key": "workflows/.../binary_data/<uuid>" }
EMA: chunk 64 < 5242880          ← single TCP-sized chunk (file fits in one frame)
debug   Running node "Upload a file1" finished successfully

For files large enough to span multiple TCP frames, the same code path emits multiple chunks of ~16 KB each, and the multipart CompleteMultipartUpload request returns EntityTooSmall with ProposedSize=16384.

File / line references

  • packages/nodes-base/nodes/Aws/S3/V2/AwsS3V2.node.ts:865 — multipart decision gate
  • packages/core/src/binary-data/binary-data.service.tsgetAsStream dispatch (forwards chunkSize)
  • packages/core/src/binary-data/object-store.manager.ts:39 — buggy getAsStream (drops chunkSize)
  • packages/core/src/binary-data/file-system.manager.ts — reference correct behaviour via highWaterMark
  • packages/cli/src/binary-data/database.manager.ts — reference correct behaviour via Readable.from(buffer)

Workaround

Set N8N_DEFAULT_BINARY_DATA_MODE=filesystem (or database). In queue / scaling mode, a shared volume that all worker pods can read/write (e.g. EFS with ReadWriteMany) is required for filesystem mode.

Operating System

Ubuntu

n8n Version

2.18.6

Node.js Version

v24.15.0

Database

PostgreSQL

Execution mode

main (default)

Hosting

self hosted

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The AWS S3 V2 node should successfully upload binary files of any size regardless of the value of N8N_DEFAULT_BINARY_DATA_MODE. Specifically, when binary data is stored in s3 mode, the multipart upload performed by the node must produce parts that respect S3's minimum part size (5 MB for non-last parts), as it does correctly in filesystem and database modes.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

n8n - 💡(How to fix) Fix AWS S3 V2 node `EntityTooSmall` error when `N8N_DEFAULT_BINARY_DATA_MODE=s3`