-
Notifications
You must be signed in to change notification settings - Fork 81
Description
When trying the nitro quickstart I had another server listening on port 3000 already, so nitro dev started up on port 3001.
When I ran curl -X POST --json '{"email":"hello@example.com"}' http://localhost:3001/api/signup it returned a 200 status and the expected response, but then I got the first error below in the nitro logs.
I then stopped my other server process and restarted nitro dev so it could listen on port 3000, and the quickstart workflow ran as expected.
Just to troubleshoot I also tried forcing it to run on port 3001 by running nitro dev --port 3001, and I got the second error below (ECONNREFUSED).
First error - caused by port conflict on start of nitro dev:
[embedded world] Failed to queue message {
queueName: '__wkf_workflow_workflow//workflows/user-signup.ts//handleUserSignup',
text: '{"message":"Route POST:/.well-known/workflow/v1/flow not found","error":"Not Found","statusCode":404}',
status: 404,
headers: {
'access-control-allow-credentials': 'true',
'access-control-allow-origin': 'http://localhost:3000/',
connection: 'keep-alive',
'content-length': '101',
'content-type': 'application/json; charset=utf-8',
date: 'Thu, 06 Nov 2025 01:24:33 GMT',
'keep-alive': 'timeout=72'
},
body: '{"runId":"wrun_01K9BC7WNWSZP85QN1G7V4110A","traceCarrier":{}}'
}
< same error repeats two more times >
[embedded world] Reached max retries of embedded world queue implementation
Second error - caused by running nitro dev --port 3001:
[unhandledRejection] TypeError: fetch failed
at node:internal/deps/undici/undici:15845:13
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async file:///path/to/my/project/node_modules/@workflow/world-local/dist/queue.js:54:34 {
[cause]: AggregateError [ECONNREFUSED]:
at internalConnectMultiple (node:net:1134:18)
at afterConnectMultiple (node:net:1715:7) {
code: 'ECONNREFUSED',
[errors]: [ [Error], [Error] ]
}
}
MRE (it's just the quickstart code):
workflows/user-signup.ts:
import { FatalError, sleep } 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);
return { userId: user.id, status: "onboarded" };
}
export 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 };
}
export 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}`);
}
export 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!");
}
}server/api/signup.post.ts:
import { start } from 'workflow/api';
import { defineEventHandler, readBody } from 'h3';
import { handleUserSignup } from "../../workflows/user-signup";
export default defineEventHandler(async (event) => {
const { email } = await readBody(event);
// Executes asynchronously and doesn't block your app
await start(handleUserSignup, [email]);
return Response.json({
message: "User signup workflow started",
});
});nitro.config.ts:
import { defineNitroConfig } from "nitropack/config"
// https://nitro.build/config
export default defineNitroConfig({
compatibilityDate: "latest",
srcDir: "server",
modules: ["workflow/nitro"],
});package.json:
{
"name": "nitro-app",
"private": true,
"scripts": {
"build": "nitro build",
"dev": "nitro dev",
"preview": "node .output/server/index.mjs"
},
"devDependencies": {
"h3": "^1.15.4",
"nitropack": "^2.12.4"
},
"dependencies": {
"workflow": "^4.0.1-beta.11"
}
}