Skip to content

Send defaulted union tags in request bodies - #42

Open
vincent0426 wants to merge 1 commit into
basetenlabs:mainfrom
vincent0426:fix/send-union-tags
Open

vincent0426 wants to merge 1 commit into
basetenlabs:mainfrom
vincent0426:fix/send-union-tags

Conversation

@vincent0426

Copy link
Copy Markdown

🚀 What

Fixes requests failing with a 400 when a model uses the default kind value. For example:

  client.api.post_models(request=CreateModelRequest(
      source=ModelArchiveSource(name="my-model", deployment=...),
  ))

fails with:

  400 Unable to extract tag using discriminator 'kind' [type=union_tag_not_found]

Today it only works if the caller passes kind="model_archive" explicitly, even though the model already defaults to it.
Go SDK always sends the tag, and JS types require it, so only Python is affected.

💻 How

Request bodies are dumped with exclude_unset, so a tag left at its default was dropped. Postprocessing now marks each defaulted tag as set on every instance, so it's always sent.

🔬 Testing

  • Added test_defaulted_union_tag_sent, which checks the request body includes kind, and test_defaulted_union_tag_set_on_validated_response. Both fail without this
    change.
  • All existing tests pass; poe lint and poe typecheck are clean.
  • Checked against the live API: the call above now gets past the tag check and fails only on the missing archive upload (A model-archive push requires the s3_key of an uploaded archive), which is expected.

Note

The spec marks the tag optional with a default, but the server requires it. Happy to close this in favor of a spec/server fix if thats better.

The spec marks the tag optional with a default, but the server requires it. Happy to close this in favor of a spec/server fix if that's better.

"ModelArchiveSourceV1": {
  "required": ["name", "deployment"],
  "properties": {
    "kind": { "const": "model_archive", "default": "model_archive", "type": "string" },
    ...

https://github.com/basetenlabs/baseten-python/blob/3f1347cecbae0fa01244f9437a3ac5d4ac7746b2/scripts/apigen/specs/management.json#L23076-L23120

The spec gives each tagged-union member's tag field (kind/typ) a
default, so the generated models default it too. Request bodies are
dumped with exclude_unset, which dropped a tag the caller left at its
default, and the server rejects the body:

  400 Unable to extract tag using discriminator 'kind'
      [type=union_tag_not_found]

For example, CreateModelRequest(source=ModelArchiveSource(name=...,
deployment=...)) sent no kind. Postprocessing now marks each defaulted
tag as set on every instance, so it is always sent, matching the Go
SDK's From* helpers. Other defaulted fields are still left to the
server.
Copilot AI balanced review requested due to automatic review settings November 9, 2026 18:43
@CLAassistant

CLAassistant commented Nov 9, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the change preserving defaulted union discriminator tags during serialization.

No open issues 🎉

What changed in this PR

Fixes Python SDK requests that omit defaulted union discriminator tags, causing server-side validation errors. The change preserves these tags during serialization while leaving unrelated unset defaults omitted.

Changes:

  • Update model postprocessing to mark defaulted discriminator fields as set.
  • Regenerate management API and model configuration models with initialization hooks.
  • Add regression tests for request serialization and validated model field tracking.
File Description
tests/​client/​test_management.py Tests default tag inclusion and preservation of other unset defaults.
scripts/​apigen/​postprocess.py Generates initialization hooks that mark defaulted discriminator fields as set.
baseten/​client/​modelconfig/​_models.py Adds hooks to protocol option models.
baseten/​client/​managementapi/​_models.py Adds hooks to tagged management API models.

Review effort: Balanced

This branch has not been deployed

No deployments
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.

3 participants