Skip to content

fix(google-discovery): JSON-safe Option encoding for persisted bindings#706

Open
aryasaatvik wants to merge 2 commits intoRhysSullivan:mainfrom
aryasaatvik:fix/google-discovery-option-encoding
Open

fix(google-discovery): JSON-safe Option encoding for persisted bindings#706
aryasaatvik wants to merge 2 commits intoRhysSullivan:mainfrom
aryasaatvik:fix/google-discovery-option-encoding

Conversation

@aryasaatvik
Copy link
Copy Markdown
Contributor

@aryasaatvik aryasaatvik commented May 8, 2026

Summary

tools.list returns 500 for any persisted google-discovery source:

Expected Option, got {"_id":"Option","_tag":"Some","value":"V1 error format."}
  at ["parameters"][0]["description"]

In Effect v4, Schema.Option(...) is a self-declaration (Type == Encoded == Option). The v4 migration (edd904c8) swapped v3's optionalWith({ as: "Option" }) for it, so encoded values still hold real Option instances. The binding column is JSON-mode, so Drizzle stringifies — Option.toJSON emits {_id, _tag, value}, which the decoder then rejects on read.

Replaced with Schema.OptionFromOptional(...) (the v4 equivalent of v3's optionalWith({as:"Option"}), already used by openapi). Runtime type stays Option<...>, encoded form is JSON-safe.

Migration

Existing rows persisted with the broken shape still fail to decode. Clear them so bindings re-derive:

  • delete + re-add the source from the UI, or
  • DELETE FROM google_discovery_binding WHERE source_id = '<id>'; and refresh.

Test plan

  • typecheck + vitest run packages/plugins/google-discovery (11/11)
  • re-add a google source locally, confirm tools.list returns 200

Schema.Option in Effect v4 is a self-declaration (Type == Encoded == Option),
so encoded values still hold real Option instances. When the binding column
(JSON-mode text) gets JSON.stringify'd, Option.toJSON emits
{_id, _tag, value} -- which decode then rejects on read with
"Expected Option, got {_id:Option,_tag:Some,value:...}", failing tools.list
with a 500.

Replace Schema.Option(...) with Schema.OptionFromOptional(...) -- the v4
equivalent of v3's optionalWith({ as: "Option" }) -- so encoded form is a
JSON-safe absent/present field while the runtime type stays Option<...>.
Matches the pattern already used by openapi.

Existing rows persisted with the broken shape need to be cleared (delete +
re-add the source, or DELETE FROM google_discovery_binding WHERE source_id =
'...') so bindings re-derive with the corrected encoding.
@aryasaatvik aryasaatvik marked this pull request as ready for review May 8, 2026 05:50
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.

1 participant