Skip to content

test: demonstrate multipart array encoding bug with arrayFmt:"comma"#86

Merged
rgarcia merged 2 commits intomainfrom
fix/multipart-array-encoding
Mar 3, 2026
Merged

test: demonstrate multipart array encoding bug with arrayFmt:"comma"#86
rgarcia merged 2 commits intomainfrom
fix/multipart-array-encoding

Conversation

@rgarcia
Copy link
Contributor

@rgarcia rgarcia commented Mar 3, 2026

Summary

  • apiform.MarshalRoot hardcodes arrayFmt:"comma" which drops array indices from multipart form field names. For endpoints with arrays of objects (like /fs/upload's files array), this produces ambiguous field names like files.dest_path / files.file instead of files.0.dest_path / files.0.file.
  • Without indices, a server cannot pair file contents with their destination paths when multiple items are uploaded — every item gets identical field names.
  • This is the root cause of kernel browsers fs upload returning 400 in production: the server-side parser requires an indexed format but gets index-less field names.

Failing tests added

Test What it checks
TestUploadFilesMultipartEncoding/single_file Even a single-file upload can't be parsed with standard indexed decoding
TestUploadFilesMultipartEncoding/multiple_files Multi-file upload produces identical field names for all items
TestUploadFilesFieldNameFormat Directly inspects field names, confirms they lack array indices
TestLoadExtensionsMultipartEncoding Same bug affects the extensions upload endpoint

Repro output

Field names produced by SDK: [files.dest_path files.file files.dest_path files.file]

Two files uploaded, but all four field names are identical — no way to correlate which file goes with which dest_path.

Fix

The fix is to change MarshalRoot to use arrayFmt:"indices:dots" (or "indices:brackets") so it produces files.0.dest_path / files.0.file (or files[0].dest_path / files[0].file). Since this SDK is Stainless-generated, this likely needs a Stainless config change.

Test plan

  • Tests fail on current main, confirming the bug exists
  • After the arrayFmt fix, all four tests should pass

Note

Medium Risk
Changes multipart form field naming for root-level arrays, which can affect server-side parsing expectations across upload-style endpoints. Risk is moderate because it alters request serialization but is covered by new integration-style tests.

Overview
Fixes multipart form encoding for root-level arrays by switching apiform.MarshalRoot from arrayFmt:"comma" to arrayFmt:"indices:dots", ensuring fields are emitted as indexed names (e.g., files.0.dest_path) instead of ambiguous repeated keys.

Adds a new multipart_array_encoding_test.go suite that spins up an httptest server to parse incoming multipart requests and asserts that Browsers.Fs.Upload and Browsers.LoadExtensions produce decodable, index-bearing field names for both single and multi-item arrays.

Written by Cursor Bugbot for commit 11a7720. This will update automatically on new commits. Configure here.

rgarcia added 2 commits March 3, 2026 16:21
The SDK's apiform.MarshalRoot hardcodes arrayFmt:"comma" which drops
array indices from multipart field names. For arrays of objects (like
the files array in /fs/upload or extensions in /browsers/{id}/extensions),
this produces ambiguous field names like "files.dest_path" and
"files.file" instead of "files.0.dest_path" and "files.0.file".

Without indices, a server cannot pair file contents with their
destination paths when multiple items are uploaded — all items share
identical field names.

These tests use httptest servers that attempt to decode the multipart
body using standard indexed field name parsing, demonstrating the
failure. Affected endpoints:
  - BrowserFUploadParams (files array)
  - BrowserLoadExtensionsParams (extensions array)

Made-with: Cursor
…rray encoding

Changes arrayFmt from "comma" to "indices:dots" in MarshalRoot so that
arrays of objects produce indexed field names (e.g. files.0.dest_path)
instead of ambiguous repeated names (e.g. files.dest_path).

This only affects the two MarshalMultipart callers that have array
fields (BrowserFUploadParams, BrowserLoadExtensionsParams). The four
callers without array fields are unaffected since the array encoder
is never invoked. The objKeyEncoder also behaves identically for both
formats (both use dot notation for nested objects).

Made-with: Cursor
@rgarcia rgarcia requested a review from sjmiller609 March 3, 2026 21:38
@rgarcia rgarcia merged commit 7f661cd into main Mar 3, 2026
5 checks passed
@rgarcia rgarcia deleted the fix/multipart-array-encoding branch March 3, 2026 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants