From 5b7cdfc01e71e6fac84d3fd8c8d67c062aaccec6 Mon Sep 17 00:00:00 2001 From: Max Strivens <74908625+mstrivens@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:23:53 +0100 Subject: [PATCH] fix: tolerate missing created_at/updated_at in LinkedAccount responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit list_linked_accounts (GET /accounts) fails to deserialize on every call for some providers. The live response omits created_at/updated_at (e.g. linkedin_lms accounts), but the spec marks both required + non-nullable. Crystalline's strict from_dict raises KeyError on the missing key while building each nested LinkedAccount. Because the /accounts 200 response is a oneOf whose branches both wrap LinkedAccount, both branches fail and the Union returns nil (0.41.0) / raised TypeError (0.40.1) — the entire page is lost over two absent timestamps on one record. Make created_at/updated_at nullable and drop them from LinkedAccount's required list so the generated model deserializes accounts that lack them. Verified by regenerating locally (speakeasy 1.638.0, lint 0 errors, SDK generated successfully) and deserializing: - the exact payload from the bug report (timestamps absent) -> ok - a full payload with timestamps present -> ok, timestamps parsed - the bare-array oneOf branch -> ok Stopgap in the Ruby overlay; the real fix belongs in the OAS producer (make the fields nullable there, or always return them) to cover all SDKs. Co-Authored-By: Claude Opus 4.8 (1M context) --- .speakeasy/ruby-modifications-overlay.yaml | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.speakeasy/ruby-modifications-overlay.yaml b/.speakeasy/ruby-modifications-overlay.yaml index 9d1a2f31..77be485e 100644 --- a/.speakeasy/ruby-modifications-overlay.yaml +++ b/.speakeasy/ruby-modifications-overlay.yaml @@ -20,6 +20,36 @@ actions: update: $ref: "#/components/schemas/StepLogPartialLegacy" + # The live GET /accounts response omits created_at/updated_at for some providers + # (e.g. linkedin_lms), but the spec marks them required + non-nullable. Crystalline's + # strict from_dict then raises KeyError on the missing key, and because the /accounts + # 200 oneOf branches both wrap LinkedAccount, the whole paginated response fails to + # deserialize (returns nil). Make the two timestamps nullable AND drop them from + # required so the generated model tolerates their absence. + - target: "$.components.schemas.LinkedAccount.properties.created_at" + description: Allow created_at to be absent/null in LinkedAccount responses + update: + nullable: true + + - target: "$.components.schemas.LinkedAccount.properties.updated_at" + description: Allow updated_at to be absent/null in LinkedAccount responses + update: + nullable: true + + - target: "$.components.schemas.LinkedAccount.required" + description: Remove created_at/updated_at from required (API omits them for some providers) + remove: true + + - target: "$.components.schemas.LinkedAccount" + description: Re-add LinkedAccount.required without the two optional timestamps + update: + required: + - id + - provider + - status + - origin_owner_id + - origin_owner_name + - target: "$.components.schemas" description: Add missing ActionsRpcResponse schema definition update: