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}`);
}
