Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] [Next 15] Dev/build error: Server Actions must be async functions #288

Open
2 tasks done
monstajoe2002 opened this issue Oct 25, 2024 · 10 comments
Open
2 tasks done
Labels
bug Something isn't working

Comments

@monstajoe2002
Copy link

Are you using the latest version of this library?

  • I verified that the issue exists in the latest next-safe-action release

Is there an existing issue for this?

  • I have searched the existing issues and found nothing that matches

Describe the bug

I just upgraded to Next.js 15 and I got this at handleValidationErrorsShape: async (ev) => flattenValidationErrors(ev) saying that this has to be an async function. To mitigate this issue I added the async keyword. However, there's a race condition within next that I have to click the submit button twice to actually get back any validation errors
image

Reproduction steps

Upgrade to next Next 15 and use handleValidationErrorsShape on a server action

Expected behavior

No error at all

Link to a minimal reproduction of the issue

https://github.com/Caramella-Corner/caramellacorner.shop/blob/master/app/admin/_actions/products.ts

Operating System

Windows 11

Library version

7

Next.js version

15.0.1

Node.js version

20.18.0

Additional context

No response

@monstajoe2002 monstajoe2002 added the bug Something isn't working label Oct 25, 2024
@TheEdoRan
Copy link
Owner

Yep, unfortunately that's the current behavior of Next.js 15, not sure if it's a bug or expected, I'm waiting for an official reply by the Next.js team. Check out this tweet.

@TheEdoRan TheEdoRan changed the title [BUG] falttenValidationErrors must be asynchronous [BUG] [Next 15] Dev/build error: Server Actions must be async functions Oct 25, 2024
@chungweileong94
Copy link

chungweileong94 commented Nov 5, 2024

unfortunately that's the current behavior of Next.js 15, not sure if it's a bug or expected

Yeah, pretty sure this is a bug. I build a similar library myself, and I'm getting the same thing as well.

What I noticed is that it only happens when Next.js encounters a "top-level" function within a "use server" file. So in cases like function chaining pattern, if you read the file from top to bottom, every functions (callbacks) that you encounter has to be an async function.

For instance:

"use server";

export action = 
    client
      .method(() => {}) // This the top-level function to Next.js bundler, and it has to be an async function
      .method2(() => {}) // This the top-level function to Next.js bundler, and it has to be an async function

The workaround is also simple, just mark them as async function. The only problem is that your linter might not like it.

@aniketbiprojit
Copy link

Yup. Build issue doesn't makes any sense.

@TheEdoRan
Copy link
Owner

Hey @chungweileong94, thanks for opening an issue in the Next.js repo. I'm linking it here for reference, as this issue is related to the framework itself rather than next-safe-action.

@raiyansarker
Copy link

any workaround for the time being? just started a new project and stuck because of this

@chungweileong94
Copy link

any workaround for the time being? just started a new project and stuck because of this

You should be able to workaround the issue by adding async in front of each function that it's complaining, event though it shouldn't be an async function, but I think it shouldn't cause any issues🤞

@raiyansarker
Copy link

any workaround for the time being? just started a new project and stuck because of this

You should be able to workaround the issue by adding async in front of each function that it's complaining, event though it shouldn't be an async function, but I think it shouldn't cause any issues🤞

can you give me an example, this is the first time, I'm using this library

@chungweileong94
Copy link

can you give me an example, this is the first time, I'm using this library

Unfortunately, it's really depends on what kind of code you have. Mind if you can share me the code snippet?

@raiyansarker
Copy link

I'm just adding contact form, heard about the library few months ago, wanted to try today, this is what I implemented so far using the docs,

"use server";

import { createSafeActionClient } from "next-safe-action";
import { z } from "zod";
import { zfd } from "zod-form-data";

export const actionClient = createSafeActionClient();

const subjects = ["project", "query", "feedback", "other"] as const;

export const contactAction = actionClient
  .schema(
    zfd.formData({
      firstName: zfd.text(z.string().min(2).max(50)),
      lastName: zfd.text(z.string().min(2).max(50)),
      email: zfd.text(z.string().email()),
      subject: zfd.text(z.enum(subjects)),
      message: zfd.text(z.string().min(10).max(1000)),
    }),
  )
  .action(async ({ parsedInput, ctx }) => {
    // Send email, save to database, etc.
    console.log(parsedInput);
    console.log(ctx);
    return {
      success: true,
    };
  });

@chungweileong94
Copy link

I'm just adding contact form, heard about the library few months ago, wanted to try today, this is what I implemented so far using the docs,

"use server";

import { createSafeActionClient } from "next-safe-action";
import { z } from "zod";
import { zfd } from "zod-form-data";

export const actionClient = createSafeActionClient();

const subjects = ["project", "query", "feedback", "other"] as const;

export const contactAction = actionClient
  .schema(
    zfd.formData({
      firstName: zfd.text(z.string().min(2).max(50)),
      lastName: zfd.text(z.string().min(2).max(50)),
      email: zfd.text(z.string().email()),
      subject: zfd.text(z.enum(subjects)),
      message: zfd.text(z.string().min(10).max(1000)),
    }),
  )
  .action(async ({ parsedInput, ctx }) => {
    // Send email, save to database, etc.
    console.log(parsedInput);
    console.log(ctx);
    return {
      success: true,
    };
  });

Ah I see, I think this doesn't share the same problem as this issue.

Basically, in your case you just have to remove the export for actionClient. Reason: If you mark a file with "use server", Next.js/React expect every exports to be an async function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants