Skip to content

fix: use indexed bracket notation for multipart array encoding#90

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

fix: use indexed bracket notation for multipart array encoding#90
rgarcia merged 2 commits intomainfrom
fix/multipart-array-encoding

Conversation

@rgarcia
Copy link
Contributor

@rgarcia rgarcia commented Mar 4, 2026

Summary

  • The SDK's addFormValue uses key + '[]' for arrays, producing field names like files[][dest_path] and files[][file] instead of files[0][dest_path] and files[0][file].
  • Without numeric indices, the server-side parser fails (strconv.Atoi("") on the empty string between []), returning 400 for all upload requests.
  • Even if parsing succeeded, multiple files would be ambiguous — no way to pair each file with its dest_path.
  • This is the same class of bug as kernel-go-sdk#86, where the Go SDK also dropped array indices.

Affected endpoints

Only two multipart endpoints have array-of-object fields and are affected:

  • fs.uploadfiles: Array<{dest_path, file}>
  • browsers.loadExtensionsextensions: Array<{name, zip_file}>

The other two multipart endpoints (deployments.create, extensions.upload) have no array fields so are unaffected by this change.

Fix

One-line change in src/internal/uploads.ts:

- await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry)));
+ await Promise.all(value.map((entry, i) => addFormValue(form, `${key}[${i}]`, entry)));

Failing tests added (commit 1)

Test What it checks
fs.upload / single file should use indexed field names Single-file upload field names contain [0]
fs.upload / multiple files should use distinct indexed field names Multi-file upload produces [0], [1], [2] and content is correctly paired
fs.upload / field names should contain array indices (direct inspection) No empty [] brackets, only numeric indices
browsers.loadExtensions / multiple extensions should use indexed field names Same bug affects extensions upload

Repro

$ node repro.mjs
=== Test 1: single file upload ===
  FAILED: 400 400 invalid form field: files[][dest_path]

Test plan

  • All 4 new tests fail on main (confirm bug exists)
  • All 4 new tests pass after fix
  • Full test suite passes (updated form.test.ts to expect bar[1] instead of bar[])
  • Lint passes (./scripts/lint)

rgarcia added 2 commits March 4, 2026 10:44
…ices

The SDK's addFormValue uses `key + '[]'` for arrays, producing field
names like `files[][dest_path]` and `files[][file]` instead of
`files[0][dest_path]` and `files[0][file]`.

Without numeric indices, a server cannot:
1. Parse the field names (strconv.Atoi("") fails on empty brackets)
2. Pair file contents with their destination paths for multi-file uploads

These tests use a mock HTTP server with busboy to capture and inspect
the actual multipart field names the SDK produces. Affected endpoints:
  - fs.upload (files array)
  - browsers.loadExtensions (extensions array)

Made-with: Cursor
Changes array encoding in addFormValue from `key + '[]'` to
`key + '[' + i + ']'` so that arrays of objects produce indexed field
names (e.g. files[0][dest_path]) instead of ambiguous empty-bracket
names (e.g. files[][dest_path]).

Without indices, the server cannot parse the field names
(strconv.Atoi("") fails on the empty string between []) and cannot
pair file contents with destination paths for multi-file uploads.

Only two multipart endpoints have array-of-object fields:
  - fs.upload (files array)
  - browsers.loadExtensions (extensions array)
The other two multipart endpoints (deployments.create, extensions.upload)
have no array fields so are unaffected.

Updates the existing form.test.ts assertion to expect the correct
indexed format (bar[1] instead of bar[]).

Made-with: Cursor
@rgarcia rgarcia force-pushed the fix/multipart-array-encoding branch from 0d41c2f to e2a7664 Compare March 4, 2026 15:47
@rgarcia rgarcia requested a review from sjmiller609 March 4, 2026 15:53
@rgarcia rgarcia merged commit b4e58af into main Mar 4, 2026
8 checks passed
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