Skip to content

@effect/platform-bun multipart.toPersisted hangs when maxTotalSize is exceeded mid-file #6284

Description

@IgnisDa

Bug

Multipart.toPersisted (and Multipart.persisted in @effect/platform-bun) hangs indefinitely when the multipart parser's maxTotalSize limit is exceeded mid-file during upload.

The request times out at 60s because the handler never completes — no response is ever sent.

Root Cause

This is caused by a bug upstream in multipasta (the multipart parsing library): the write() function returns early without forwarding the chunk to the boundary scanner when maxTotalSize is exceeded.

The chain:

  1. multipasta's write() (src/internal/multipart.ts) checks maxTotalSize before split.write(). When exceeded, it calls onError and returns — the boundary scanner never sees the chunk.
  2. multipasta's web wrapper (src/web.ts): the onFile callback sets finished only when onChunk(null) is called. This never happens because the scanner never processes the boundary ending the current file part.
  3. @effect/platform-bun's persisted (dist/esm/internal/multipart.js:18-44): calls reader.readMany() in a loop waiting for the file's readable stream to close. It never does → hang.
  4. @effect/platform's toPersisted: uses Stream.runForEach which awaits the writer callback for each part sequentially. So the outer stream's MultipartError is never observed — the handler never completes, no response is sent.

Key Distinction

Limit Effect
maxPartSize (per-file) Error fires, but file readable closes normally — chunk was already forwarded to scanner
maxTotalSize (whole-request) Error fires, but file readable hangs — scanner never sees trailing boundary

Upstream Fix

The fix is in multipasta: tim-smart/multipasta#38 — the write() method should still forward the chunk to split.write() after calling onError, so the boundary scanner can close the current file part's readable.

Once multipasta is fixed, @effect/platform-bun will need to bump the multipasta dependency.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions