Skip to content

[BUG] ResultAsync.fromPromise fails with React 19 server components' Promise transmission #643

@gtoxlili

Description

@gtoxlili

Issue Description

When using the Server Actions feature of React 19, an error occurs when passing the promise object passed from the server directly to ResultAsync.fromPromise():
Error: Cannot read properties of undefined (reading ‘catch’). Cannot read properties of undefined (reading ‘catch’) `

Reproduction Steps

  1. Create a React application with Next.js, enable Server Components and Server Actions.
  2. Create a Server Action that returns a promise.
  3. Try wrapping the promise directly in a client or server component with ResultAsync.fromPromise.

Minimal Reproduction Code

// lib/serverActions.ts
'use server'

export async function fetchData() {
    // Return a Server Action promise
    return {data: "Some data"};
}

// Server Component
async function ServerComponent() {
    const dataPromise = fetchData(); // Promise transmitted to client

    return <><DataComponent dataPromise={dataPromise} /><DataComponent dataPromise={dataPromise} /></>
}

// components/DataComponent.tsx
'use client'

import {ResultAsync} from 'neverthrow';
import {useEffect, useState} from 'react';

export default function DataComponent({dataPromise}) {
    const [data, setData] = useState(null);

    useEffect(() => {
        // This will fail here:. Error. Cannot read properties of undefined (reading 'catch')
        ResultAsync.fromPromise(dataPromise, error =>
            console.error("Failed to load data:", error)
        ).match(
            value => setData(value),
            error => console.error(error)
        );
    }, [dataPromise]);
}

return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>;
}

Error Message

Error. Cannot read properties of undefined (reading 'catch') 

Workaround

This can be resolved by creating an intermediate asynchronous function to wrap the Server Action promise:

// Create an intermediate async function: 
const interimProgram = async () => dataPromise; 
ResultAsync.fromPromise(interimProgram(), error => 
 console.error("Failed to load data:", error) 
).match( 
 value => setData(value), 
 error => console.error(error) 
); 

Additional Context

This issue only occurs when using the Server Actions feature of React 19. React 19 seems to have special handling of promises, and these promise objects may not fully conform to the standard Promise interface, causing neverthrow to not be handled correctly.

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