diff --git a/fixtures/flight/src/Button.js b/fixtures/flight/src/Button.js
index 811fb8da76ffb..bbdaeba2bde9c 100644
--- a/fixtures/flight/src/Button.js
+++ b/fixtures/flight/src/Button.js
@@ -3,11 +3,21 @@
import * as React from 'react';
export default function Button({action, children}) {
+ const [isPending, setIsPending] = React.useState(false);
+
return (
diff --git a/fixtures/flight/src/actions.js b/fixtures/flight/src/actions.js
index 6534908e01ed6..f7dccd6a62f65 100644
--- a/fixtures/flight/src/actions.js
+++ b/fixtures/flight/src/actions.js
@@ -1,6 +1,13 @@
'use server';
export async function like() {
- console.log('Like');
- return 'Liked';
+ return new Promise((resolve, reject) =>
+ setTimeout(
+ () =>
+ Math.random() > 0.5
+ ? resolve('Liked')
+ : reject(new Error('Failed to like')),
+ 500
+ )
+ );
}
diff --git a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
index 157301ba58e0b..348aba5ee9ac0 100644
--- a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
+++ b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
@@ -850,4 +850,49 @@ describe('ReactFlightDOMBrowser', () => {
const result = await actionProxy('!');
expect(result).toBe('Hello World!');
});
+
+ it('propagates server reference errors to the client', async () => {
+ let actionProxy;
+
+ function Client({action}) {
+ actionProxy = action;
+ return 'Click Me';
+ }
+
+ async function send(text) {
+ return Promise.reject(new Error(`Error for ${text}`));
+ }
+
+ const ServerModule = serverExports({send});
+ const ClientRef = clientExports(Client);
+
+ const stream = ReactServerDOMWriter.renderToReadableStream(
+ ,
+ webpackMap,
+ );
+
+ const response = ReactServerDOMReader.createFromReadableStream(stream, {
+ async callServer(ref, args) {
+ const fn = requireServerRef(ref);
+ return ReactServerDOMReader.createFromReadableStream(
+ ReactServerDOMWriter.renderToReadableStream(fn.apply(null, args)),
+ );
+ },
+ });
+
+ function App() {
+ return use(response);
+ }
+
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ await act(async () => {
+ root.render();
+ });
+
+ const expectedError = new Error('Error for test');
+ spyOnDevAndProd(console, 'error').mockImplementation(() => {});
+ await expect(actionProxy('test')).rejects.toThrow(expectedError);
+ expect(console.error.mock.calls).toEqual([[expectedError]]);
+ });
});
diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js
index 20800530b831c..f610f99b49161 100644
--- a/packages/react-server/src/ReactFlightServer.js
+++ b/packages/react-server/src/ReactFlightServer.js
@@ -293,6 +293,8 @@ function serializeThenable(request: Request, thenable: Thenable): number {
} else {
emitErrorChunkProd(request, newTask.id, digest);
}
+ newTask.status = ERRORED;
+ pingTask(request, newTask);
},
);