Skip to content

Client event iterator returns proxy events breaking applications that exepect structuredClone to work #977

@muniter

Description

@muniter

Environment

orpc@1.17.11, node 24

Reproduction

Simply have a procedure that's an event iterator: https://orpc.unnoq.com/docs/event-iterator or use the recommended ai sdk integration https://orpc.unnoq.com/docs/integrations/ai-sdk#ai-sdk-integration and console.log the parts

      for await (const part of e) {
        console.log(part);
      }

You will see Proxy(Object) {type: 'start', messageMetadata: {…}, messageId: 'smsg-xYxxCOuD2sKB00wg'}

If you want to trigger an error using the ai sdk just write a data part using the UI writer.

         writer.write({
            type: "data-suggested-action",
            data: {
              type: "something",
            },
          });

Describe the bug

Returning proxy objects instead of plain objects causes issues in downstream consumers who expect a stream of plain objects.

Right now the AI SDK sometimes calls structuredClone on the messages (seems like when it gets data parts) and structure cloning a proxy throws an error.

Stack trace:

chat-component.tsx:158 DataCloneError: Failed to execute 'structuredClone' on 'Window': #<Object> could not be cloned.
    at ReactChatState.snapshot (@ai-sdk_react.js?v=f8f26246:4058:32)
    at ReactChatState.replaceMessage (@ai-sdk_react.js?v=f8f26246:4053:14)
    at write (@ai-sdk_react.js?v=f8f26246:2818:28)
    at @ai-sdk_react.js?v=f8f26246:2002:17
    at @ai-sdk_react.js?v=f8f26246:2811:17
    at Array.<anonymous> (@ai-sdk_react.js?v=f8f26246:2087:17)
    at SerialJobExecutor.processQueue (@ai-sdk_react.js?v=f8f26246:2078:26)
    at @ai-sdk_react.js?v=f8f26246:2093:17
    at new Promise (<anonymous>)
    at SerialJobExecutor.run (@ai-sdk_react.js?v=f8f26246:2084:12)

Overall I think the right approach is for the orpc client to not return proxy objects in the event iterator, given event iterator is the only option we have to send streams keeping things as plain as possible seems to be for the best to avoid compatibility issues with other libraries.

Additional context

No response

Logs

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions