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>
kraenhansen
pushed a commit
that referenced
this pull request
Aug 5, 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) --------- Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com>
Merged
kraenhansen
added a commit
that referenced
this pull request
Aug 6, 2026
The create-dubbing-project endpoint gained a new webhook_ids field, which shifted the context of the Fern Replay patch #825 so its body hunk no longer applied: `import json` was removed but `json.dumps(...)` was left behind for both keyterms and webhook_ids, breaking mypy (and raising NameError at runtime). Extend the fix to both fields so it matches the TS SDK (repeated form fields). Fern Replay will re-derive the patch to cover webhook_ids on the next regen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kraenhansen
added a commit
that referenced
this pull request
Aug 6, 2026
* [fern-generated] Update SDK Generated by Fern CLI Version: unknown Generators: - fernapi/fern-python-sdk: 4.64.1 * [fern-replay] Applied customizations Patches with unresolved conflicts (1): - patch-560b8934: fix: send list-of-primitive multipart fields as repeated form fields (#819) (#825) Run `fern-replay resolve` to apply these customizations. * fix: send dubbing keyterms/webhook_ids as repeated multipart form fields The create-dubbing-project endpoint gained a new webhook_ids field, which shifted the context of the Fern Replay patch #825 so its body hunk no longer applied: `import json` was removed but `json.dumps(...)` was left behind for both keyterms and webhook_ids, breaking mypy (and raising NameError at runtime). Extend the fix to both fields so it matches the TS SDK (repeated form fields). Fern Replay will re-derive the patch to cover webhook_ids on the next regen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com> Co-authored-by: Kræn Hansen <kraen@elevenlabs.io> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merged
kraenhansen
added a commit
that referenced
this pull request
Aug 11, 2026
Fern regeneration reverted the #825 fix and dropped the json import, breaking mypy and re-introducing the original multipart bug.
kraenhansen
added a commit
that referenced
this pull request
Aug 11, 2026
* [fern-generated] Update SDK Generated by Fern CLI Version: unknown Generators: - fernapi/fern-python-sdk: 4.64.1 * [fern-replay] Applied customizations Patches with unresolved conflicts (1): - patch-560b8934: fix: send list-of-primitive multipart fields as repeated form fields (#819) (#825) Run `fern-replay resolve` to apply these customizations. Patches absorbed by generator (1): - patch-e1cf8db9: Add missing realtime speech-to-text options (#830) The generator now produces these customizations natively. * fix: preserve repeated-form-field encoding for keyterms/webhook_ids Fern regeneration reverted the #825 fix and dropped the json import, breaking mypy and re-introducing the original multipart bug. --------- Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com> Co-authored-by: Kræn Hansen <kraen@elevenlabs.io>
PaulAsjes
added a commit
that referenced
this pull request
Aug 12, 2026
…ients - delete src/elevenlabs/realtime/, realtime_tts.py and the speech_to_text_custom wrapper: client.text_to_speech.realtime(...) and client.speech_to_text.realtime(...) are now generated (sync + async) - narrow the speech_engine .fernignore entry from the whole directory to the hand-written session/server/resource layer only, so the generated REST + socket clients regenerate in place; hand-written types.py renamed to session_types.py to make room for the generated types/ package - restore music/raw_client.py to pure generated output and prune the stale replay.lock patch (#825) — the 5.x generator implements the repeated-form-fields fix natively - CI bumps python 3.8 -> 3.10 (quoted; unquoted 3.10 parses as 3.1) - test_ttv switched from removed create_previews to design Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Merged
kraenhansen
added a commit
that referenced
this pull request
Aug 13, 2026
Fern regeneration reverted the #825 fix and dropped the json import, breaking mypy and re-introducing the original multipart bug.
kraenhansen
added a commit
that referenced
this pull request
Aug 13, 2026
* [fern-generated] Update SDK Generated by Fern CLI Version: unknown Generators: - fernapi/fern-python-sdk: 4.64.1 * [fern-replay] Applied customizations Patches with unresolved conflicts (1): - patch-560b8934: fix: send list-of-primitive multipart fields as repeated form fields (#819) (#825) Run `fern-replay resolve` to apply these customizations. * fix: preserve repeated-form-field encoding for keyterms/webhook_ids Fern regeneration reverted the #825 fix and dropped the json import, breaking mypy and re-introducing the original multipart bug. --------- Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com> Co-authored-by: Kræn Hansen <kraen@elevenlabs.io>
Closed
Merged
kraenhansen
added a commit
that referenced
this pull request
Aug 25, 2026
Fern regeneration reverted the #825 fix again, re-wrapping both fields in json.dumps and dropping the json import, which breaks mypy and re-introduces the original multipart bug. Third recurrence, after #845 and the fix on the branch closed with #851. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kraenhansen
added a commit
that referenced
this pull request
Aug 25, 2026
Fern regeneration reverted the #825 fix again, re-wrapping both fields in json.dumps and dropping the json import, which breaks mypy and re-introduces the original multipart bug. Third recurrence, after #845 and the fix on the branch closed with #851. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kraenhansen
added a commit
that referenced
this pull request
Aug 25, 2026
* [fern-generated] Update SDK Generated by Fern CLI Version: unknown Generators: - fernapi/fern-python-sdk: 4.64.1 * [fern-replay] Applied customizations Patches with unresolved conflicts (1): - patch-560b8934: fix: send list-of-primitive multipart fields as repeated form fields (#819) (#825) Run `fern-replay resolve` to apply these customizations. * fix: preserve repeated-form-field encoding for keyterms/webhook_ids Fern regeneration reverted the #825 fix again, re-wrapping both fields in json.dumps and dropping the json import, which breaks mypy and re-introduces the original multipart bug. Third recurrence, after #845 and the fix on the branch closed with #851. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: fern-api[bot] <115122769+fern-api[bot]@users.noreply.github.com> Co-authored-by: Kræn Hansen <kraen@elevenlabs.io> Co-authored-by: Claude Opus 5 <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