Skip to content

fix: Cast paginated list items to their element type - #113

Merged
gjtorikian merged 2 commits into
mainfrom
pagination-fixup
Aug 5, 2026
Merged

fix: Cast paginated list items to their element type#113
gjtorikian merged 2 commits into
mainfrom
pagination-fixup

Conversation

@gjtorikian

@gjtorikian gjtorikian commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #112. Requires workos/oagen-emitters#210 — this branch is the regenerated output of that emitter fix.

Summary

  • 35 of 40 paginated endpoints returned items with every field dropped. Page.from_map/4 casts each element of data, but the generated code passed the *List envelope's from_map/1 instead of the element's. Every item came back as an empty %FooList{object: "list", data: nil, list_metadata: nil}, and reading a real field raised KeyError. The reporter hit it on list_organization_memberships; it also affected list_users, list_invitations, list_user_api_keys, all of WorkOS.Authorization, and 28 more.
  • Only 5 endpoints were correct — exactly the ones with no named envelope in the spec (AuditLogAction, AuditLogSchema, RedirectUri, CORSOriginResponse, UserSessionsListItem), confirming the reporter's codegen hypothesis.
  • 3.0.0 shipped green because the fixtures and assertions were wrong in the same direction. The generated fixture nested an envelope inside data — a shape the API never returns — the test asserted %WorkOS.UserList{object: "list"}, and the @spec claimed Page.t(UserList.t()), so dialyzer agreed as well. The bug was self-consistent end to end.
  • The *List envelope structs are removed. Once the caster was fixed, 24 of 27 were referenced by nothing. Page is what these functions have always returned, so the envelopes only ever surfaced as the empty husks this bug produced. VersionListResponse and GroupRoleAssignmentList remain — non-paginated endpoints return them by name.
  • The second commit is unrelated spec drift (agent.registration.refreshed) that the regeneration picked up. Split out so this fix can be reviewed and released on its own.

Compatibility

This drops 47 modules from the public surface, so code that named a *List struct in a @spec or pattern match will no longer compile. In practice that code could only ever have been working around this bug — the structs were never populated with anything.

Fixes #112. Every list endpoint with a named `*List` envelope in the
spec cast each item with the envelope's `from_map/1` rather than the
element's, so 35 of 40 paginated endpoints returned items with every
field dropped and `membership.organization_id` raised `KeyError`.

3.0.0 shipped this with a green suite because the generated fixtures
and assertions were wrong in the same direction: the fixture nested an
envelope inside `data` — a shape the API never returns — the test
asserted the envelope struct, and the `@spec` claimed
`Page.t(FooList.t())`, so dialyzer saw a consistent story too.

Regenerated with the emitter fix in workos/oagen-emitters#210. The
`*List` envelope structs go away with it: `Page` is what these
functions have always returned, and the envelope structs only ever
surfaced as the empty husks this bug produced. The two envelopes that
non-paginated endpoints return by name (`VersionListResponse`,
`GroupRoleAssignmentList`) are unaffected.
Spec drift the regeneration for #112 picked up, unrelated to that fix.
Kept separate so the pagination fix can be reviewed, released, or
reverted on its own.
@gjtorikian
gjtorikian requested a review from a team as a code owner August 5, 2026 19:40
@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown

Too many files changed for review (131 files, 100 file limit).

Bypass the limit by tagging @greptile-apps to review.

@workos-sdk-automation

Copy link
Copy Markdown
Contributor

🤖 This pull request was closed automatically

It edits files that are auto-generated by (each file has a header comment identifying it as generated). Hand edits to generated code are overwritten the next time the SDK is regenerated from the OpenAPI spec, so they can't be merged.

Generated files changed outside their hand-maintainable regions:

  • lib/workos/agent_registration_refreshed.ex
  • lib/workos/agent_registration_refreshed_data.ex
  • lib/workos/api_keys.ex
  • lib/workos/authorization.ex
  • lib/workos/authorization_permission_list.ex
  • lib/workos/authorization_permission_list_list_metadata.ex
  • lib/workos/authorization_resource_list.ex
  • lib/workos/authorization_resource_list_list_metadata.ex
  • lib/workos/authorized_connect_application_list.ex
  • lib/workos/authorized_connect_application_list_list_metadata.ex
  • lib/workos/connect.ex
  • lib/workos/connect_application_list.ex
  • lib/workos/connect_application_list_list_metadata.ex
  • lib/workos/connection_list.ex
  • lib/workos/connection_list_list_metadata.ex
  • lib/workos/create_webhook_endpoint_events.ex
  • lib/workos/data_integration_list.ex
  • lib/workos/data_integration_list_list_metadata.ex
  • lib/workos/directory_group_list.ex
  • lib/workos/directory_group_list_list_metadata.ex
  • lib/workos/directory_list.ex
  • lib/workos/directory_list_list_metadata.ex
  • lib/workos/directory_sync.ex
  • lib/workos/directory_user_list.ex
  • lib/workos/directory_user_list_list_metadata.ex
  • lib/workos/event_list.ex
  • lib/workos/event_list_list_metadata.ex
  • lib/workos/events.ex
  • lib/workos/feature_flags.ex
  • lib/workos/flag_list.ex
  • lib/workos/flag_list_list_metadata.ex
  • lib/workos/group_list.ex
  • lib/workos/group_list_list_metadata.ex
  • lib/workos/groups.ex
  • lib/workos/multi_factor_auth.ex
  • lib/workos/object_list_response.ex
  • lib/workos/organization_api_key_list.ex
  • lib/workos/organization_api_key_list_list_metadata.ex
  • lib/workos/organization_authorized_connect_application_list.ex
  • lib/workos/organization_authorized_connect_application_list_list_metadata.ex
  • lib/workos/organization_list.ex
  • lib/workos/organization_list_list_metadata.ex
  • lib/workos/organization_membership_service.ex
  • lib/workos/organizations.ex
  • lib/workos/pipes.ex
  • lib/workos/sso.ex
  • lib/workos/update_webhook_endpoint_events.ex
  • lib/workos/user_api_key_list.ex
  • lib/workos/user_api_key_list_list_metadata.ex
  • lib/workos/user_authentication_factor_list.ex
  • lib/workos/user_authentication_factor_list_list_metadata.ex
  • lib/workos/user_invite_list.ex
  • lib/workos/user_invite_list_list_metadata.ex
  • lib/workos/user_list.ex
  • lib/workos/user_list_list_metadata.ex
  • lib/workos/user_management.ex
  • lib/workos/user_organization_membership_base_list.ex
  • lib/workos/user_organization_membership_base_list_list_metadata.ex
  • lib/workos/user_organization_membership_list.ex
  • lib/workos/user_organization_membership_list_list_metadata.ex
  • lib/workos/user_role_assignment_list.ex
  • lib/workos/user_role_assignment_list_list_metadata.ex
  • lib/workos/vault.ex
  • lib/workos/webhook_endpoint_list.ex
  • lib/workos/webhook_endpoint_list_list_metadata.ex
  • lib/workos/webhooks.ex
  • test/workos/api_keys_round_trip_test.exs
  • test/workos/api_keys_test.exs
  • test/workos/authorization_round_trip_test.exs
  • test/workos/authorization_test.exs
  • test/workos/connect_round_trip_test.exs
  • test/workos/connect_test.exs
  • test/workos/directory_sync_round_trip_test.exs
  • test/workos/directory_sync_test.exs
  • test/workos/events_round_trip_test.exs
  • test/workos/events_test.exs
  • test/workos/feature_flags_round_trip_test.exs
  • test/workos/feature_flags_test.exs
  • test/workos/groups_round_trip_test.exs
  • test/workos/groups_test.exs
  • test/workos/multi_factor_auth_round_trip_test.exs
  • test/workos/multi_factor_auth_test.exs
  • test/workos/organization_membership_service_round_trip_test.exs
  • test/workos/organization_membership_service_test.exs
  • test/workos/organizations_round_trip_test.exs
  • test/workos/organizations_test.exs
  • test/workos/pipes_round_trip_test.exs
  • test/workos/pipes_test.exs
  • test/workos/sso_round_trip_test.exs
  • test/workos/sso_test.exs
  • test/workos/user_management_round_trip_test.exs
  • test/workos/user_management_test.exs
  • test/workos/vault_round_trip_test.exs
  • test/workos/vault_test.exs
  • test/workos/webhooks_round_trip_test.exs
  • test/workos/webhooks_test.exs

What to do instead

  • Generated code (models, resources, client wiring): make the change upstream in the OpenAPI spec so it lands on the next regeneration.
  • Hand-maintained code inside a generated file: only the regions fenced by @oagen-ignore-start@oagen-ignore-end may be edited by hand. Keep your changes within those fences.
  • Adding, moving, or removing a fence (@oagen-ignore-start / @oagen-ignore-end): fence boundaries are owned by the generator, so they can't change in a hand-authored PR. This must come from a regeneration PR (opened by the SDK Automation Bot or carrying the autogenerated label).

If you believe this was closed in error, a maintainer can reopen the PR.

@gjtorikian gjtorikian reopened this Aug 5, 2026
@gjtorikian
gjtorikian merged commit 44d886b into main Aug 5, 2026
15 of 16 checks passed
@gjtorikian
gjtorikian deleted the pagination-fixup branch August 5, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

list_* functions pass the collection type to Page.from_map, so every item parses to an empty wrapper (3.0.0)

1 participant