fix: send list-of-primitive multipart fields as repeated form fields (#819) - #825
Merged
Merged
Conversation
…819) Interim hotfix for the v2.59.0 regression introduced by generator fern-python-sdk 4.46.9 (commit cb4feb824, PR fern-api/fern#11284), which began serializing every non-scalar multipart form field via json.dumps(jsonable_encoder(...)). List[str] fields are not scalar primitives, so they were sent as a single JSON-array string instead of repeated form fields -- causing the API to validate the whole array against per-item limits (e.g. speech_to_text keyterms -> invalid_keyword_length). Reverts the 8 list-of-primitive fields to raw values so httpx emits repeated form fields, matching generator fix 5.22.2. Object fields (labels, entity_detection, entity_redaction, webhook_metadata) keep json.dumps. Removes now-unused json / jsonable_encoder imports. This is intended to be carried across regenerations by Fern Replay and retired (`fern replay forget`) once the 4.x backport of 5.22.2 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PaulAsjes
approved these changes
Jul 29, 2026
This was referenced Jul 30, 2026
kraenhansen
pushed a commit
that referenced
this pull request
Jul 30, 2026
* [fern-generated] Update SDK Generated by Fern CLI Version: unknown Generators: - fernapi/fern-python-sdk: 4.64.1 * [fern-replay] Applied customizations Patches applied (1): - patch-560b8934: fix: send list-of-primitive multipart fields as repeated form fields (#819) (#825) Patches with unresolved conflicts (1): - patch-1b45413e: [Speech Engine] Add disable_auth parameter (#806) Run `fern-replay resolve` to apply these customizations. --------- Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com>
4 tasks
kraenhansen
added a commit
that referenced
this pull request
Jul 30, 2026
…#828) patch-1b45413e was captured from "[Speech Engine] Add disable_auth parameter (#806)", but its remaining diff is only a hardcoded version bump (2.55.0 to 2.56.0) plus websockets >=13.0 (now native via the generator config). Because it pins an old version string, it collided with the version line on every regeneration and surfaced as an unresolved conflict (most recently in the v2.60.0 regen PR #826). Running `fern replay forget patch-1b45413e` drops it from the active patch set and tombstones its content hash so it is not re-captured. The #825 multipart fix (patch-560b8934) is unaffected, and disable_auth itself is generated from the spec and does not depend on this patch. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Interim fix for #819.
speech_to_text.convert(keyterms=[...])(and other multipart list fields) fails withinvalid_keyword_lengthbecause the whole list is sent as one JSON-array string instead of repeated form fields.Root cause (verified): generator
fern-python-sdk4.46.9 (commitcb4feb824, PR fern-api/fern#11284, 2026-01-08) added an_is_primitive_type()gate to multipart serialization: only scalar primitives are sent directly, everything else — includingList[str]— isjson.dumps(jsonable_encoder(...))'d. PR #817 bumped us onto that behavior (4.42.0 → 4.64.1). The change was undocumented — it shipped bundled inside a "fix python wire tests" PR. Fixed upstream in generator 5.22.2, but that's past the 5.5.4 min-Python-3.10 clamp, so we can't just upgrade forward.This hand-edits Fern-generated files, so it must be retired once the generator itself emits the correct code. Revert (via
fern replay forget <patch-id>, then regenerate) as soon as either of these is true:5.22.2— the version that fixes list-of-primitive multipart serialization (fix-multipart-list-of-primitives-repeated-fields.yml).≥ 5.5.4raises the generated min-Python to 3.10 — only take this path once we're ready for that breaking change.4.xbackport of the 5.22.2 fix lands (requested from Fern) and we pin to it — keeps Python 3.8 support and fixes the bug, at which point this patch is fully redundant.Until then, Fern Replay re-applies this patch on every regeneration. Leaving it in place after the generator is fixed will cause a 3-way-merge conflict (both sides changing the same lines) surfaced in the regeneration PR body — that conflict is the signal to run
fern replay forgetand drop this patch.Change
Reverts the 8 list-of-primitive (
List[str]) multipart fields to raw values so httpx emits repeated form fields, matching generator 5.22.2 semantics:speech_to_text/raw_client.pykeytermsdubbing/project/raw_client.pykeytermsmusic/raw_client.pytagsmusic/finetunes/raw_client.pytagsstudio/projects/raw_client.pygenres,pronunciation_dictionary_locators,voice_settingsaudio_native/raw_client.pypronunciation_dictionary_locatorsObject fields (
labels,entity_detection,entity_redaction,webhook_metadata) keepjson.dumps— correct for multipart. Now-unusedjson/jsonable_encoderimports removed.Durability
These are generated files, so the edit is carried across regenerations by Fern Replay (auto-captured as a patch in
.fern/replay.lock). See the revert conditions above for how it is retired.Test plan
ruff@0.11.5(E/F/I) passes on all 6 filespy_compilepasses on all 6 filesspeech_to_text.convert(keyterms=[...])no longer returnsinvalid_keyword_lengthagainst the live APIpatches detected: 1)Fixes #819
🤖 Generated with Claude Code