WorkflowRuntimeError: 'start' received an invalid workflow function - Hono/Nitro

We have a workflow function (Hono) that works locally, but not on Vercel. I deployed another (barebones) app using Workflow SDK’s walkthrough for Hono and that seems to work, so I’m not sure what the difference could be.

The below code works fine locally, but gives the pictured error when deployed to Vercel. The workflow itself is just the example from the docs.

We have some other middleware in our Hono app that I will leave out, but I don’t think it should be affecting anything. Is Nitro required for deployment. Our production branch of the API is not using Nitro, though we can use Nitro if that’s the only way to get workflows working. I’m not clear on the pros and cons of this.

Using pnpm. Have tried with various versions of workflow sdk and get the same error.

export default defineNitroConfig({
	preset: 'vercel',
	sourcemap: true,
  modules: ["workflow/nitro"],
  routes: {
    "/**": "./src/app.ts"
  },
	alias: { "#app": fileURLToPath(new URL("./src", import.meta.url)) },
	rollupConfig: {
    plugins: [
      sentryRollupPlugin({
        authToken: process.env.SENTRY_AUTH_TOKEN,
        org: "redacted",
        project: "redacted",
        release: { name: release, finalize: true, setCommits: { auto: true } }
      }),
    ],
  }
});
app.post("/api/signup", async (c) => {
	try {
		const { email } = await c.req.json()
		await start(handleUserSignup, [email])
		return c.json({ message: "User signup workflow started" })
	} catch (error) {
		console.error(error)
		// @ts-expect-error
		return c.json({ message: error?.message || "Workflow error" }, 500)
	}
})
import { sleep } from "workflow";
import { FatalError } from "workflow";

export async function handleUserSignup(email: string) {
  "use workflow"; 
  const user = await createUser(email);
  await sendWelcomeEmail(user);
  await sleep("5s"); // Pause for 5s - doesn't consume any resources
  await sendOnboardingEmail(user);
  console.log("Workflow is complete! Run 'npx workflow web' to inspect your run")
  return { userId: user.id, status: "onboarded" };
}

async function createUser(email: string) {
  "use step"; 
  console.log(`Creating user with email: ${email}`);
  // Full Node.js access - database calls, APIs, etc.
  return { id: crypto.randomUUID(), email };
}

async function sendWelcomeEmail(user: { id: string; email: string }) {
  "use step"; 
  console.log(`Sending welcome email to user: ${user.id}`);
  if (Math.random() < 0.3) {
    // By default, steps will be retried for unhandled errors
    throw new Error("Retryable!");
  }
}

async function sendOnboardingEmail(user: { id: string; email: string }) {
  "use step"; 
  if (!user.email.includes("@")) {
    // To skip retrying, throw a FatalError instead
    throw new FatalError("Invalid Email");
  }
  console.log(`Sending onboarding email to user: ${user.id}`);
}

Hi, sorry for the late reply here

The code looks correct as you have it, so my best guesses would either be

  • you are using hono build instead of nitro build and therefore the workflows are not being compiled
  • the sentry plugin is conflicting with the workflow somehow

Can you check both of those?

We are using nitro build and it was the same without the sentry plugin.

I seemed to get this resolved by passing ‘framework’: ‘nitro’ in the vercel json. Before it was hono and seems like Vercel was doing some special things there.

Do we have to wrap our hono app in nitro to use workflows? We currently have our API working fine with just the normal vercel hono configuration (no build step and hono preset).

The framework setting tells Vercel where to look in the build output for the server handlers, so if Nitro is serving the workflow endpoints, you need the matching framework setting in order to get them live on Vercel.

The Workflow Devkit requires two things

  • a compiler
  • a server

Nitro can be both of those, which is why most of the Workflow framework integrations in the docs use it, it was just the easiest way to get support for many frameworks quickly

Hono is already a server, so if you’re ok stitching some things together yourself you can use the workflow CLI as the compiler, and then you’ll be able to set the Vercel framework back to hono. This guide shows how to set up an integration by hand for Bun Serve, which should be pretty close to how it works in Hono too

Ran into this issue as well with Hono, and adding framework: nitro to the vercel.json solved the problem as mentioned in the thread.

Would it just be a better practice to use Nitro (as oppsoed to Hono) to begin with for service that will be primarily used for workflows?