December 2, 2025
200 OK, SDK says nope?
Forward compatibility and fault tolerance in TypeScript API Clients/SDKs
Devs split: “Don’t crash” update vs “Types must scream”
TLDR: Speakeasy’s TypeScript SDKs now accept unknown values and go easy on missing fields, so apps don’t crash when servers change. The comments are split: pragmatists love fewer fires, purists warn relaxed types can hide bugs—but everyone hates the “200 OK then error” chaos.
Speakeasy just rolled out a fix for the classic tech soap opera: you get a “200 OK” from the server yet your app throws a fit. Their TypeScript SDKs now accept unknown values in lists (called enums) and mix-and-match types (unions), and go lax when a field is missing—meaning fewer crashes when servers evolve. It’s on by default, and you can turn it off. Fans are cheering in the threads, posting “my SDK gaslit me” memes and celebrating fewer late-night on-call fires. One commenter called it “the end of the ‘200 OK then scream’ era.” Announcement. But the drama is rich. The type-safety purists are clutching pearls, insisting this opens the door to sneaky bugs: unknown is how bugs hide. Pragmatists clap back that real servers don’t stay perfect forever and apps should be resilient. Some compare the move to Go and Pydantic being chill about weird data, while skeptics argue client-side “forgiveness” just masks sloppy backends. The funniest hot take: “TypeScript turning into JavaScript in a suit, with ‘UNKNOWN’ cufflinks.” Meanwhile, a war of words erupts over whether versioning every response is realistic, or whether smart clients should just roll with the punches. One thing everyone agrees on: that “200 OK but SDK explodes” moment has to die.
Key Points
- •SDKs can raise errors on 200 responses due to API evolution and inaccurate OpenAPI specs causing strict validation failures.
- •Server-side strategies include versioned client tagging, validation layers, spec generation from implementation, generated backend adapters, and contract testing.
- •Speakeasy TypeScript SDKs enable forward-compatible enums by default, allowing unknown values; control via gen.yaml and x-speakeasy-unknown-values.
- •Forward-compatible unions accept unknown discriminators via an UNKNOWN member with raw data; configurable per union via gen.yaml and OpenAPI extension.
- •A default lax mode tolerates missing required fields during deserialization, inspired by Go JSON unmarshal and Pydantic coercion.