Skip to content

Fix UpdateMetadata serializer to allow null values (per-key removal)#22

Merged
Haakam21 merged 2 commits into
mainfrom
fix/update-metadata-nullable-serializer
May 30, 2026
Merged

Fix UpdateMetadata serializer to allow null values (per-key removal)#22
Haakam21 merged 2 commits into
mainfrom
fix/update-metadata-nullable-serializer

Conversation

@SanjithSambath

Copy link
Copy Markdown
Contributor

Problem

inboxes.update is documented to remove a metadata key by sending it with a null value ({ metadata: { key: null } }). As of 0.5.6 the type allows this — UpdateMetadata = Record<string, MetadataValue | null> — but the serializer does not:

// before
core.serialization.record(core.serialization.string(), MetadataValue)

MetadataValue is undiscriminatedUnion([string, number, boolean]) with no null member, and record() applies it to every value with no null handling. So at runtime:

UpdateMetadata.jsonOrThrow({ foo: null }, { omitUndefined: true })
// ❌ THROWS: foo: Expected string/number/boolean. Received null.

Per-key removal compiles but throws before the request is sent — null can never reach the API. (Whole-object clear metadata: null was unaffected, since optional().json() already passes null through; only the per-key value case was broken.)

Fix

Wrap the record value schema in .nullable() so null short-circuits through serialization:

// after
core.serialization.record(core.serialization.string(), MetadataValue.nullable())

Verified:

record(string(), MetadataValue.nullable()).jsonOrThrow({ foo: null }, { omitUndefined: true })
// ✅ { "foo": null }

This also makes the runtime schema match the declared Schema<UpdateMetadata.Raw, AgentMail.inboxes.UpdateMetadata> annotation (.Raw already includes | null). tsc --project ./tsconfig.cjs.json --noEmit passes.

Root cause / follow-up

This is an upstream codegen bug: fern-typescript-node-sdk@3.60.0 honors nullable<T> in the type layer but drops .nullable() in the serialization layer for record/map values (.nullable() is emitted nowhere in the generated serialization despite the def using nullable<>).

This PR is a manual edit to a generated file as an interim fix — it will be overwritten on the next fern generate unless the generator is upgraded. Reported to the Fern team separately; the durable fix is a generator bump.

🤖 Generated with Claude Code

The UpdateMetadata type is `Record<string, MetadataValue | null>` (null on a
key removes it), but the serializer wrapped the value in a non-nullable
`MetadataValue` schema. At runtime `jsonOrThrow({ key: null })` therefore
threw — null could never be sent, so per-key metadata removal via
`inboxes.update` was impossible despite compiling.

Wrap the record value in `.nullable()` so null short-circuits through
serialization. This also aligns the runtime schema with the declared
`Schema<UpdateMetadata.Raw, UpdateMetadata>` type (Raw already includes
`| null`).

Root cause is upstream: fern-typescript-node-sdk@3.60.0 honors `nullable<T>`
in the type layer but drops `.nullable()` in the serialization layer for
record/map values. This is a manual edit to the generated file pending a
generator fix; it will need re-applying after the next `fern generate` unless
the generator is upgraded.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot 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.

No issues found across 1 file

Re-trigger cubic

Add the hand-patched serializer to .fernignore so Fern regeneration does
not overwrite the null-value fix (per-key removal).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Haakam21 Haakam21 merged commit 4ded5a9 into main May 30, 2026
4 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