[I] ~/projects/monolaw/apps/web discovery ❯ bun run dev 15:30:43
$ vite --port 3000
Generated route tree in 131ms
3:31:12 PM [vite] (client) Re-optimizing dependencies because vite config has changed
VITE v7.0.4 ready in 1072 ms
➜ Local: http://localhost:3000/
➜ Network: use --host to expose
➜ press h + enter to show help
[vite] connected.
Error reading routerStream: g [Error]: The value [object Object] of type "object" cannot be parsed/serialized.
There are few workarounds for this problem:
- Transform the value in a way that it can be serialized.
- If the reference is present on multiple runtimes (isomorphic), you can use the Reference API to map the references.
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31059)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseProperties (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:32428)
at G.parsePlainObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:28700)
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:29897)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseProperties (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:32428)
at G.parsePlainObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:28700)
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:29897)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseItems (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:27974)
at G.parseArray (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:28031)
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:29705)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseProperties (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:32428)
at G.parsePlainObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:28700)
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:29897)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseWithError (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:34024)
at G.start (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:34088)
at gr (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:35486)
at Object.dehydrate (file:///Users/litewarp/projects/monolaw/node_modules/@tanstack/router-core/dist/esm/ssr/ssr-server.js:76:7)
at async executeRouter (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:206:19)
at async eval (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:432:22)
at async next (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:448:20)
at async handleServerRoutes (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:406:17)
at async eval (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:221:48)
at async startRequestResolver (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:126:24)
at async file:///Users/litewarp/projects/monolaw/node_modules/@tanstack/start-plugin-core/dist/esm/dev-server-plugin/plugin.js:47:30 {
value: RelayModernEnvironment {
configName: undefined,
_treatMissingFieldsAsNull: false,
__log: [Function: emptyFunction],
relayFieldLogger: [Function: defaultRelayFieldLogger],
_defaultRenderPolicy: 'partial',
_operationLoader: undefined,
_operationExecutions: Map(0) {},
_network: { execute: [Function: execute] },
_getDataID: [Function: defaultGetDataID],
_missingFieldHandlers: [],
_publishQueue: RelayPublishQueue {
_hasStoreSnapshot: false,
_handlerProvider: [Function: RelayDefaultHandlerProvider],
_pendingBackupRebase: false,
_pendingData: Set(0) {},
_pendingOptimisticUpdates: Set(0) {},
_store: [RelayModernStore],
_appliedOptimisticUpdates: Set(0) {},
_gcHold: null,
_getDataID: [Function: defaultGetDataID],
_missingFieldHandlers: [],
_log: [Function: emptyFunction]
},
_scheduler: null,
_store: RelayModernStore {
_gcStep: [Function (anonymous)],
_currentWriteEpoch: 0,
_gcHoldCounter: 0,
_gcReleaseBufferSize: 10,
_shouldRetainWithinTTL_EXPERIMENTAL: false,
_gcRun: null,
_gcScheduler: [Function: resolveImmediate],
_getDataID: [Function: defaultGetDataID],
_globalInvalidationEpoch: null,
_invalidationSubscriptions: Set(0) {},
_invalidatedRecordIDs: Set(0) {},
__log: null,
_queryCacheExpirationTime: undefined,
_operationLoader: null,
_optimisticSource: null,
_recordSource: [RelayRecordSource],
_releaseBuffer: [],
_roots: [Map],
_shouldScheduleGC: false,
_resolverCache: [LiveResolverCache],
_resolverContext: undefined,
_storeSubscriptions: [RelayStoreSubscriptions],
_updatedRecordIDs: Set(0) {},
_shouldProcessClientComponents: false,
_treatMissingFieldsAsNull: false,
_actorIdentifier: undefined
},
options: undefined,
_isServer: false,
_normalizeResponse: [Function: normalizeResponse],
__setNet: [Function (anonymous)],
DEBUG_inspect: [Function (anonymous)],
_operationTracker: RelayOperationTracker {
_ownersToPendingOperations: Map(0) {},
_pendingOperationsToOwners: Map(0) {},
_ownersToPendingPromise: Map(0) {}
},
_shouldProcessClientComponents: undefined
}
}
node:internal/process/promises:394
triggerUncaughtException(err, true /* fromPromise */);
^
g [Error]: The value [object Object] of type "object" cannot be parsed/serialized.
There are few workarounds for this problem:
- Transform the value in a way that it can be serialized.
- If the reference is present on multiple runtimes (isomorphic), you can use the Reference API to map the references.
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31059)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseProperties (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:32428)
at G.parsePlainObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:28700)
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:29897)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseProperties (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:32428)
at G.parsePlainObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:28700)
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:29897)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseItems (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:27974)
at G.parseArray (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:28031)
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:29705)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseProperties (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:32428)
at G.parsePlainObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:28700)
at G.parseObject (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:29897)
at G.parse (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:31430)
at G.parseWithError (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:34024)
at G.start (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:34088)
at gr (file:///Users/litewarp/projects/monolaw/node_modules/seroval/dist/esm/production/index.mjs:17:35486)
at Object.dehydrate (file:///Users/litewarp/projects/monolaw/node_modules/@tanstack/router-core/dist/esm/ssr/ssr-server.js:76:7)
at async executeRouter (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:206:19)
at async eval (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:432:22)
at async next (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:448:20)
at async handleServerRoutes (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:406:17)
at async eval (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:221:48)
at async startRequestResolver (/Users/litewarp/projects/monolaw/node_modules/@tanstack/start-server-core/src/createStartHandler.ts:126:24)
at async file:///Users/litewarp/projects/monolaw/node_modules/@tanstack/start-plugin-core/dist/esm/dev-server-plugin/plugin.js:47:30 {
value: RelayModernEnvironment {
configName: undefined,
_treatMissingFieldsAsNull: false,
__log: [Function: emptyFunction],
relayFieldLogger: [Function: defaultRelayFieldLogger],
_defaultRenderPolicy: 'partial',
_operationLoader: undefined,
_operationExecutions: Map(0) {},
_network: { execute: [Function: execute] },
_getDataID: [Function: defaultGetDataID],
_missingFieldHandlers: [],
_publishQueue: RelayPublishQueue {
_hasStoreSnapshot: false,
_handlerProvider: [Function: RelayDefaultHandlerProvider],
_pendingBackupRebase: false,
_pendingData: Set(0) {},
_pendingOptimisticUpdates: Set(0) {},
_store: <ref *1> RelayModernStore {
_gcStep: [Function (anonymous)],
_currentWriteEpoch: 0,
_gcHoldCounter: 0,
_gcReleaseBufferSize: 10,
_shouldRetainWithinTTL_EXPERIMENTAL: false,
_gcRun: null,
_gcScheduler: [Function: resolveImmediate],
_getDataID: [Function: defaultGetDataID],
_globalInvalidationEpoch: null,
_invalidationSubscriptions: Set(0) {},
_invalidatedRecordIDs: Set(0) {},
__log: null,
_queryCacheExpirationTime: undefined,
_operationLoader: null,
_optimisticSource: null,
_recordSource: RelayRecordSource {
_records: Map(1) { 'client:root' => [Object] }
},
_releaseBuffer: [],
_roots: Map(2) {
'fe6e1c0b4dcd701df1db506c58582afa{}' => {
operation: [Object],
refCount: 1,
epoch: null,
fetchTime: null
},
'676406b84ab53ec0f13ad7ce05cfa13a{"filter":{"storageBucket":{"equalToInsensitive":"uploads"}},"first":20,"offset":0,"orderBy":["CREATED_AT_ASC"]}' => {
operation: [Object],
refCount: 1,
epoch: null,
fetchTime: null
}
},
_shouldScheduleGC: false,
_resolverCache: LiveResolverCache {
_resolverIDToRecordIDs: Map(0) {},
_recordIDToResolverIDs: Map(0) {},
_getRecordSource: [Function (anonymous)],
_store: [Circular *1],
_handlingBatch: false,
_liveResolverBatchRecordSource: null
},
_resolverContext: undefined,
_storeSubscriptions: RelayStoreSubscriptions {
_subscriptions: Set(0) {},
__log: undefined,
_resolverCache: LiveResolverCache {
_resolverIDToRecordIDs: Map(0) {},
_recordIDToResolverIDs: Map(0) {},
_getRecordSource: [Function (anonymous)],
_store: [Circular *1],
_handlingBatch: false,
_liveResolverBatchRecordSource: null
},
_resolverContext: undefined
},
_updatedRecordIDs: Set(0) {},
_shouldProcessClientComponents: false,
_treatMissingFieldsAsNull: false,
_actorIdentifier: undefined
},
_appliedOptimisticUpdates: Set(0) {},
_gcHold: null,
_getDataID: [Function: defaultGetDataID],
_missingFieldHandlers: [],
_log: [Function: emptyFunction]
},
_scheduler: null,
_store: <ref *1> RelayModernStore {
_gcStep: [Function (anonymous)],
_currentWriteEpoch: 0,
_gcHoldCounter: 0,
_gcReleaseBufferSize: 10,
_shouldRetainWithinTTL_EXPERIMENTAL: false,
_gcRun: null,
_gcScheduler: [Function: resolveImmediate],
_getDataID: [Function: defaultGetDataID],
_globalInvalidationEpoch: null,
_invalidationSubscriptions: Set(0) {},
_invalidatedRecordIDs: Set(0) {},
__log: null,
_queryCacheExpirationTime: undefined,
_operationLoader: null,
_optimisticSource: null,
_recordSource: RelayRecordSource {
_records: Map(1) {
'client:root' => { __id: 'client:root', __typename: '__Root' }
}
},
_releaseBuffer: [],
_roots: Map(2) {
'fe6e1c0b4dcd701df1db506c58582afa{}' => {
operation: { fragment: [Object], request: [Object], root: [Object] },
refCount: 1,
epoch: null,
fetchTime: null
},
'676406b84ab53ec0f13ad7ce05cfa13a{"filter":{"storageBucket":{"equalToInsensitive":"uploads"}},"first":20,"offset":0,"orderBy":["CREATED_AT_ASC"]}' => {
operation: { fragment: [Object], request: [Object], root: [Object] },
refCount: 1,
epoch: null,
fetchTime: null
}
},
_shouldScheduleGC: false,
_resolverCache: LiveResolverCache {
_resolverIDToRecordIDs: Map(0) {},
_recordIDToResolverIDs: Map(0) {},
_getRecordSource: [Function (anonymous)],
_store: [Circular *1],
_handlingBatch: false,
_liveResolverBatchRecordSource: null
},
_resolverContext: undefined,
_storeSubscriptions: RelayStoreSubscriptions {
_subscriptions: Set(0) {},
__log: undefined,
_resolverCache: LiveResolverCache {
_resolverIDToRecordIDs: Map(0) {},
_recordIDToResolverIDs: Map(0) {},
_getRecordSource: [Function (anonymous)],
_store: [Circular *1],
_handlingBatch: false,
_liveResolverBatchRecordSource: null
},
_resolverContext: undefined
},
_updatedRecordIDs: Set(0) {},
_shouldProcessClientComponents: false,
_treatMissingFieldsAsNull: false,
_actorIdentifier: undefined
},
options: undefined,
_isServer: false,
_normalizeResponse: [Function: normalizeResponse],
__setNet: [Function (anonymous)],
DEBUG_inspect: [Function (anonymous)],
_operationTracker: RelayOperationTracker {
_ownersToPendingOperations: Map(0) {},
_pendingOperationsToOwners: Map(0) {},
_ownersToPendingPromise: Map(0) {}
},
_shouldProcessClientComponents: undefined
}
}
Node.js v22.13.1
error: script "dev" exited with code 1
Last active
July 11, 2025 22:38
-
-
Save litewarp/e4d1e82054298a17c923d6af3dbcca8b to your computer and use it in GitHub Desktop.
Debugging Seroval in @tanstack/start
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { User } from "@monolaw/auth"; | |
import { | |
type RecordMap, | |
RecordSource, | |
type RelayEnvironment, | |
RelayEnvironmentProvider, | |
} from "@monolaw/relay-esm"; | |
import type { AnyRouter } from "@tanstack/react-router"; | |
import { Fragment } from "react"; | |
import { createPreloader } from "./preloader.ts"; | |
export interface RelayRouterContext { | |
environment: RelayEnvironment; | |
user: User | null; | |
preloadQuery: ReturnType<typeof createPreloader>; | |
} | |
type AdditionalOptions = { | |
WrapProvider?: (props: { children: any }) => React.JSX.Element; | |
/** | |
* If `true`, the QueryClient will handle errors thrown by `redirect()` inside of mutations and queries. | |
* | |
* @default true | |
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction) | |
*/ | |
handleRedirects?: boolean; | |
}; | |
export type ValidateRouter<TRouter extends AnyRouter> = NonNullable< | |
TRouter["options"]["context"] | |
> extends RelayRouterContext | |
? TRouter | |
: never; | |
interface DehydratedRouterQueryState<TOptions = Record<string, unknown>> { | |
dehydratedEnvironment?: { | |
options: TOptions; | |
recordSource: RecordMap; | |
}; | |
// queryStream: ReadableStream<Record<string, unknown>>; | |
} | |
export function createRelayRouter< | |
TRouter extends AnyRouter, | |
TEnvironment extends RelayEnvironment, | |
>( | |
router: ValidateRouter<TRouter>, | |
environment: TEnvironment, | |
additionalOpts?: AdditionalOptions, | |
): TRouter { | |
// const seenQueryKeys = new Set<string>(); | |
// const streamedQueryKeys = new Set<string>(); | |
const ogOptions = router.options; | |
router.options = { | |
...router.options, | |
context: { | |
...ogOptions.context, | |
environment: environment, | |
preloadQuery: createPreloader(environment), | |
}, | |
Wrap: ({ children }) => { | |
const OuterWrapper = additionalOpts?.WrapProvider || Fragment; | |
const OGWrap = ogOptions.Wrap || Fragment; | |
return ( | |
<OuterWrapper> | |
<RelayEnvironmentProvider environment={environment}> | |
<OGWrap>{children}</OGWrap> | |
</RelayEnvironmentProvider> | |
</OuterWrapper> | |
); | |
}, | |
}; | |
if (router.isServer) { | |
// const queryStream = createPushableStream(); | |
router.options.dehydrate = async (): Promise<DehydratedRouterQueryState> => { | |
const ogDehydrated = await ogOptions?.dehydrate?.(); | |
const dehydratedEnvironment = { | |
options: environment.options, | |
recordSource: environment.getStore().getSource().toJSON(), | |
}; | |
// router.serverSsr!.onRenderFinished(() => queryStream.close()); | |
const dehydratedRouter = { | |
...ogDehydrated, | |
dehydratedEnvironment, | |
// queryStream, | |
}; | |
return dehydratedRouter; | |
}; | |
// add environment subscriber to push data | |
} else { | |
router.options.hydrate = async (dehydrated: DehydratedRouterQueryState) => { | |
await ogOptions.hydrate?.(dehydrated); | |
// on the clinet, hydrate the query client with the dehydrated data | |
if (dehydrated.dehydratedEnvironment?.recordSource) { | |
environment | |
.getStore() | |
.publish(new RecordSource(dehydrated.dehydratedEnvironment.recordSource)); | |
} | |
// const reader = dehydrated.queryStream.getReader(); | |
// reader | |
// .read() | |
// .then(async function handle({ done, value }) { | |
// // push to store? | |
// console.log(value); | |
// if (done) return; | |
// const result = await reader.read(); | |
// return handle(result); | |
// }) | |
// .catch((err) => { | |
// console.error(`Error reading query stream: ${err}`); | |
// }); | |
}; | |
} | |
return router; | |
} | |
interface PushableStream { | |
stream: ReadableStream; | |
enqueue: (chunk: unknown) => void; | |
close: () => void; | |
isClosed: () => boolean; | |
error: (err: unknown) => void; | |
} | |
function createPushableStream(): PushableStream { | |
let controllerRef: ReadableStreamDefaultController; | |
const stream = new ReadableStream({ | |
start(controller) { | |
controllerRef = controller; | |
}, | |
}); | |
let _isClosed = false; | |
return { | |
stream, | |
enqueue: (chunk) => controllerRef.enqueue(chunk), | |
close: () => { | |
controllerRef.close(); | |
_isClosed = true; | |
}, | |
isClosed: () => _isClosed, | |
error: (err: unknown) => controllerRef.error(err), | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment