Merged
Size
S
Change Breakdown
Bug Fix85%
Testing15%
#28217fix(core): Propagate formidable parse errors in Form Trigger

Form Trigger now surfaces upload errors instead of silently failing

When file uploads via Form Trigger encountered errors (exceeding size limits, corrupted data, or parse failures), users saw misleading failures downstream instead of the actual problem. The fix propagates the real error so workflows fail clearly.

When a file upload via the Form Trigger node caused formidable's multipart parser to error internally, the failure was silently discarded. The _err parameter in formidable's callback was prefixed with _, a convention signaling an unused variable — but the error was actually needed. When formidable errored, files became undefined, the Form Trigger emitted an item with no binary data, and any downstream node expecting an uploaded file threw a confusing, unrelated error.

This PR changes that. The error callback parameter is now checked and the promise rejects when formidable reports a problem. Users see the actual failure — a file exceeding the size limit now surfaces as an HTTP 413 with a clear message, not as "No audio files found" three nodes later.

The fix lives in the CLI's webhook handling, specifically where multipart form data is parsed. Normal uploads under the size limit continue to work exactly as before — the success path is unaffected.

View Original GitHub Description

Summary

The multipart form data parser in createMultiFormDataParser silently discards errors from formidable. The callback's error parameter is prefixed with _ and never checked:

form.parse(req, async (_err, data, files) => {
    // _err is ignored — any formidable error silently produces empty files
    normalizeFormData(data);
    normalizeFormData(files);
    resolve({ data, files });
});

When formidable encounters an error (e.g. file exceeding maxFileSize, corrupted multipart stream, or any internal parse failure), data and files are empty/undefined. The promise resolves with empty objects, causing the Form Trigger to emit items with no binary data. Downstream nodes then fail with misleading errors (e.g. "No uploaded audio files were found") instead of surfacing the actual upload failure.

This PR checks the error parameter and rejects the promise when formidable reports an error, so the real failure reason reaches the user.

What changed:

  • webhook-form-data.ts: Check formidable's error callback; reject instead of silently resolving
  • webhook-form-data.test.ts: Updated the "file too large" test to expect rejection; added a second test verifying the error contains useful info (message + HTTP 413 status)

Verification

I verified the fix by running real HTTP multipart requests through formidable (v3.5.4) with a file size exceeding maxFileSize:

Before (old code — silent swallow):

Had error from formidable: true
Error message: options.maxTotalFileSize (1024 bytes) exceeded, received 2048 bytes of file data
Data keys: []
File keys: []
=> BUG: Error silently swallowed. User gets empty data.

Formidable does report the error in its callback, but the old code ignores it and resolves with empty objects. The Form Trigger then emits an item with no binary data, and downstream nodes throw confusing, unrelated errors.

After (new code — error propagated):

Error surfaced: options.maxTotalFileSize (1024 bytes) exceeded, received 2048 bytes of file data
HTTP code: 413
=> FIX: User sees the actual error instead of empty data.

The error now rejects the promise, propagates through parseRequestBodyexecuteWebhook's outer catch (line 927 of webhook-helpers.ts), and surfaces to the user as an OperationalError with the real formidable error as the cause.

Success path (no regression):

Data keys: [ 'name' ]
File keys: [ 'file' ]
=> Success path still works correctly.

Files under the limit still parse and resolve normally.

Fixes #28069

Related Linear tickets, Github issues, and Community forum posts

  • Fixes #28069

Review / Merge checklist

© 2026 · via Gitpulse