Encountered Cannot find module '@workflow-worlds/redis' when deploying a Vercel Workflow DevKit app using Nitro and Docker? This guide explains the root cause and shows how adjusting the WORKDIR fixes the issue. Includes full Dockerfile example and detailed setup instructions.
Written by: Chia1104 CC BY-NC-SA 4.0
Recently, while using Vercel’s Workflow DevKit to handle the task queue architecture for generating embeddings, I ran into a problem with the Redis PUB/SUB module @workflow-worlds/redis.
When deploying, I encountered a “module not found” error:
Cannot find module '@workflow-worlds/redis'Since I was using a Monorepo setup and my backend was served through Nitro, my project structure looked like this:
After Nitro finished building, it produced a .output folder along with a transpiled node_modules structure:
At that time, my Dockerfile looked like this:
ARG NODE_VERSION=24
FROM node:${NODE_VERSION}-alpine AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
ENV TURBO_TELEMETRY_DISABLED=1
WORKDIR /app
RUN apk update && \
apk add --no-cache \
python3 \
build-base \
gcc \
libc6-compat && \
npm install -g corepack@latest && \
corepack enable pnpm && \
pnpm add -g turbo && \
ln -sf /usr/bin/python3 /usr/bin/python
FROM base AS pre-builder
COPY . .
RUN turbo prune --scope=service --docker
FROM base AS builder
COPY --from=pre-builder /app/out/json/ .
COPY --from=pre-builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
COPY --from=pre-builder /app/out/full/ .
COPY turbo.json turbo.json
ARG TURBO_TEAM \
TURBO_TOKEN
ENV TURBO_TEAM=$TURBO_TEAM \
TURBO_TOKEN=$TURBO_TOKEN
RUN pnpm i
RUN pnpm turbo run build --filter=service...
FROM base AS runner
COPY --from=builder /app/apps/service/.output/server ./apps/service
ENV NODE_ENV=production \
PORT=8080
EXPOSE 8080
CMD [ "node", "app/apps/service/index.mjs" ]All layers share the same working directory (/app). Since Workflow dynamically loads the target module via the WORKFLOW_TARGET_WORLD environment variable within @workflow/core/runtime, it uses the following logic:
const require = createRequire(join(process.cwd(), 'index.js'));This means the module resolution depends on the current working directory from which Node is executed. Therefore, the entrypoint that starts the server must be at the same directory level as the node_modules folder containing @workflow-worlds/redis.
Adjust the WORKDIR setting:
ARG NODE_VERSION=24
FROM node:${NODE_VERSION}-alpine AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
ENV TURBO_TELEMETRY_DISABLED=1
WORKDIR /app
RUN apk update && \
apk add --no-cache \
python3 \
build-base \
gcc \
libc6-compat && \
npm install -g corepack@latest && \
corepack enable pnpm && \
pnpm add -g turbo && \
ln -sf /usr/bin/python3 /usr/bin/python
FROM base AS pre-builder
COPY . .
RUN turbo prune --scope=service --docker
FROM base AS builder
COPY --from=pre-builder /app/out/json/ .
COPY --from=pre-builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
COPY --from=pre-builder /app/out/full/ .
COPY turbo.json turbo.json
ARG TURBO_TEAM \
TURBO_TOKEN
ENV TURBO_TEAM=$TURBO_TEAM \
TURBO_TOKEN=$TURBO_TOKEN
RUN pnpm i
RUN pnpm turbo run build --filter=service...
FROM base AS runner
COPY --from=builder /app/apps/service/.output/server ./apps/service
ENV NODE_ENV=production \
PORT=8080
WORKDIR /app/apps/service
EXPOSE 8080
CMD [ "node", "index.mjs" ]