Skip to content

Initial observeFragmentExperimental snapshot during onHydrated has missing non-null linked fields #59

@dahlia

Description

@dahlia

I'm seeing a production crash during hydration. I'm not sure whether this belongs in solid-relay or Relay's experimental fragment observer, but I wanted to start here because the subscription is created from solid-relay's onHydrated path.

When that path subscribes to observeFragmentExperimental, the first emitted snapshot has the aliased connection fields missing from the fragment data. Those fields are non-null in the schema, and the generated Relay type also treats them as present after a complete read, so the component crashes reading actor.followersCount.totalCount.

The fragment:

fragment ProfileCard_actor on Actor {
  followeesCount: followees { totalCount }
  followersCount: followers { totalCount }
  # ...
}

Generated type declares followersCount as { readonly totalCount: number }, not nullable. The schema has followers: ActorFollowersConnection!.

Stacktrace (condensed)

TypeError: Cannot read properties of undefined (reading 'totalCount')

solid.js:294                      onHydrated fires
solid-relay:291                   subscribes to observeFragmentExperimental
RelayObservable.js:135            subscribe
observeFragmentExperimental.js:64 sink.next(snapshotToFragmentState(...))
ProfileCard.tsx:254               plural(actor.followersCount.totalCount, { ... })

The sequence is: onHydrated fires → solid-relay subscribes to observeFragmentExperimental → the observable immediately emits an initial snapshot → that snapshot is missing the followers/followees linked fields → crash.

I'm not sure which layer is responsible. A few possibilities I can think of: solid-relay may be subscribing before the store has finished reconciling SSR data; observeFragmentExperimental may be emitting a partial snapshot that violates the non-null contract; or the SSR payload may be writing the connection under a different storage key than the one read by the fragment (since followers is used here without args, while other queries might fetch it with pagination args). Happy to dig further if any of these sounds familiar.

Workaround

Optional chaining avoids the crash (actor.followersCount?.totalCount ?? 0), but it works around the generated type rather than explaining why the initial snapshot is missing the field.

Environment

  • solid-relay: 1.0.0-beta.20
  • relay-runtime: 19.0.0
  • solid-js: 1.9.12

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions