Which component is affected?
Qwik Rollup / Vite plugin
Describe the bug
When using “async tasks” in qwik v2, deno task build fails “intermittently.”
“Async tasks” include:
useAsync$(...)
useTask$(async () => { await ... })
useTask$(() => { return new Promise(...) })
The build either succeeds, or fails with this error message from Rollup, randomly:
error during build:
Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(vite-plugin-qwik-router-server-fns) load "\u0000virtual:qwik-router-server-fns"
at Process.handleBeforeExit (file:///tmp/testrace/node_modules/.deno/rollup@4.60.1/node_modules/rollup/dist/es/shared/node-entry.js:23313:28)
at Object.onceWrapper (ext:deno_node/_events.mjs:564:12)
at Process.emit (ext:deno_node/_events.mjs:439:20)
at Process.emit (node:process:432:38)
at dispatchProcessBeforeExitEvent (node:process:879:13)
The problem is Deno-only. Building with Node.js and Bun proceed normally.
Reproduction
https://stackblitz.com/edit/github-5balyysx?file=src%2Froutes%2Findex.tsx
Steps to reproduce
Create a qwik v2 app:
cd /tmp
deno run -A npm:create-qwik@2.0.0-beta.31 empty testrace -i
cd testrace
Write minimal useAsync$ code:
// src/routes/index.tsx
import { component$, useAsync$ } from "@qwik.dev/core";
export default component$(() => {
const fruit = useAsync$<string>(() =>
new Promise((resolve) => resolve("apple"))
);
return <div>Fruit: {fruit.value}</div>;
});
Add ssg adapter and build with Deno:
deno task qwik add ssg
deno task build
Sometimes (not everytime) Rollup fails with this:
error during build:
Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(vite-plugin-qwik-router-server-fns) load "\u0000virtual:qwik-router-server-fns"
at Process.handleBeforeExit (file:///tmp/testrace/node_modules/.deno/rollup@4.60.1/node_modules/rollup/dist/es/shared/node-entry.js:23313:28)
at Object.onceWrapper (ext:deno_node/_events.mjs:564:12)
at Process.emit (ext:deno_node/_events.mjs:439:20)
at Process.emit (node:process:432:38)
at dispatchProcessBeforeExitEvent (node:process:879:13)
Full build log
$ deno task build
Task build qwik build
............
.::: :--------:.
.:::: .:-------:.
.:::::. .:-------.
::::::. .:------.
::::::. :-----:
::::::. .:-----.
:::::::. .-----.
::::::::.. ---:.
.:::::::::. :-:.
..::::::::::::
...::::
deno run build.types
deno run build.client
deno run build.server
deno run lint
Task build.types tsc --incremental --noEmit "--pretty"
Task build.client vite build
vite v7.3.1 building client environment for production...
✓ 60 modules transformed.
dist/assets/Dzh8xAVZ-bundle-graph.json 1.07 kB │ gzip: 0.66 kB
dist/q-manifest.json 30.25 kB │ gzip: 4.22 kB
dist/build/q-Byp9lfIg.js 0.11 kB │ gzip: 0.12 kB
dist/build/q-CPEBto7H.js 0.13 kB │ gzip: 0.13 kB
dist/build/q-Czi1LwSX.js 0.15 kB │ gzip: 0.14 kB
dist/build/q-DBgbZXTS.js 0.18 kB │ gzip: 0.17 kB
dist/build/q-Ai7h09MO.js 0.19 kB │ gzip: 0.17 kB
dist/build/q-DWQ3sDuw.js 0.20 kB │ gzip: 0.19 kB
dist/build/q-5XCLoW3i.js 0.24 kB │ gzip: 0.20 kB
dist/build/q-Cc9Qra6O.js 0.31 kB │ gzip: 0.25 kB
dist/build/q-BntSa9pJ.js 0.39 kB │ gzip: 0.25 kB
dist/build/q-fmG5G1zC.js 0.53 kB │ gzip: 0.33 kB
dist/build/q-tNFKMFKY.js 0.53 kB │ gzip: 0.36 kB
dist/build/q-CaDOpu5t.js 0.55 kB │ gzip: 0.34 kB
dist/build/q-CysUL0ow.js 0.63 kB │ gzip: 0.34 kB
dist/build/q-BKT_gTbX.js 0.80 kB │ gzip: 0.47 kB
dist/build/q-CcNa2poI.js 0.89 kB │ gzip: 0.54 kB
dist/build/q-ogTKInb-.js 0.90 kB │ gzip: 0.52 kB
dist/build/q-RPUTNPji.js 0.90 kB │ gzip: 0.55 kB
dist/build/q-BvmD9iPO.js 1.36 kB │ gzip: 0.76 kB
dist/build/q-xmCVacXr.js 1.55 kB │ gzip: 0.84 kB
dist/build/q-0jgfnq-U.js 1.99 kB │ gzip: 0.98 kB
dist/build/q-B9id7zUI.js 2.62 kB │ gzip: 1.02 kB
dist/build/q-7wzWdMr9.js 3.66 kB │ gzip: 1.87 kB
dist/build/q-VPloE5mA.js 4.76 kB │ gzip: 2.42 kB
dist/build/q-B81hBnHe.js 7.20 kB │ gzip: 2.92 kB
dist/build/q-AZviV0SD.js 11.15 kB │ gzip: 4.82 kB
dist/build/q-Amb1vhsw.js 97.84 kB │ gzip: 37.54 kB
✓ built in 923ms
✓ Built client modules
Task build.server qwik check-client src dist && vite build -c adapters/ssg/vite.config.ts
Task lint eslint "src/**/*.ts*"
............
.::: :--------:.
.:::: .:-------:.
.:::::. .:-------.
::::::. .:------.
::::::. :-----:
::::::. .:-----.
:::::::. .-----.
::::::::.. ---:.
.:::::::::. :-:.
..::::::::::::
...::::
vite v7.3.1 building ssr environment for production...
transforming (33) node_modules/.deno/@qwik.dev+router@2.0.0-beta.31/node_modules/@qwik.dev/router/lib/chunks/error-handler.mjsRead client manifest from /tmp/testrace/dist/q-manifest.json
✗ Build failed in 414ms
error during build:
Unexpected early exit. This happens when Promises returned by plugins cannot resolve. Unfinished hook action(s) on exit:
(vite-plugin-qwik-router-server-fns) load "\u0000virtual:qwik-router-server-fns"
at Process.handleBeforeExit (file:///tmp/testrace/node_modules/.deno/rollup@4.60.1/node_modules/rollup/dist/es/shared/node-entry.js:23313:28)
at Object.onceWrapper (ext:deno_node/_events.mjs:564:12)
at Process.emit (ext:deno_node/_events.mjs:439:20)
at Process.emit (node:process:432:38)
at dispatchProcessBeforeExitEvent (node:process:879:13)
undefined
ExecaError: Command failed with exit code 1: deno run build.server
useTask$ with promises has same problem too.
import { component$, useSignal, useTask$ } from "@qwik.dev/core";
export default component$(() => {
const fruit = useSignal("");
useTask$(async () => {
fruit.value = await new Promise((resolve) => resolve("apple"));
});
return <div>Fruit: {fruit.value}</div>;
});
System Info
System:
OS: Linux 6.19 Debian GNU/Linux forky/sid
CPU: (16) x64 AMD Eng Sample: 100-000000300-40_Y
Memory: 17.32 GB / 30.75 GB
Container: Yes
Shell: 5.3.9 - /usr/bin/bash
Binaries:
Node: 25.6.1 - /opt/app/node/current/bin/node
npm: 11.9.0 - /opt/app/node/current/bin/npm
bun: 1.3.11 - /opt/app/bun-linux-x64/bun
Deno: 2.7.12 - /opt/app/deno
Browsers:
Chromium: 146.0.7680.177
Firefox: 140.9.0esr
Firefox Developer Edition: 140.9.0esr
* My system isn’t a container, but a minimal Debian system installed with `debootstrap`. It shouldn’t matter anyway ;)
Additional Information
The problem is very possibly upstream (of Deno or Vite/Rollup), but given their complexity, I don’t have time to verify it.
I suspect these code in Rollup around the given node_modules/rollup/dist/es/shared/node-entry.js:23313:28:
async function catchUnfinishedHookActions(pluginDriver, callback) {
const emptyEventLoopPromise = new Promise((_, reject) => {
// ...
reject(new Error(`Unexpected early exit. This happens when Promises returned by plugins cannot resolve. ...
// ...
});
try {
return await Promise.race([callback(), emptyEventLoopPromise]);
}
// ...
Probably Promise.race (or the event loop) behavior differs in Deno? I’m wondering if we can have migrations in qwik codebase.
It’s unknown if the problem will persist after the Rolldown migration (#8379).
The reproduction url contains code, but the environment only has node.js 18. If possible, verify locally with Deno, try running deno task build may times (like more than 5).
EDIT: useTask$(() => { new Promise(...); return void 0; }); is anti-pattern, should always return the promise(s).
Which component is affected?
Qwik Rollup / Vite plugin
Describe the bug
When using “async tasks” in qwik v2,
deno task buildfails “intermittently.”“Async tasks” include:
useAsync$(...)useTask$(async () => { await ... })useTask$(() => { return new Promise(...) })The build either succeeds, or fails with this error message from Rollup, randomly:
The problem is Deno-only. Building with Node.js and Bun proceed normally.
Reproduction
https://stackblitz.com/edit/github-5balyysx?file=src%2Froutes%2Findex.tsx
Steps to reproduce
Create a qwik v2 app:
Write minimal
useAsync$code:Add
ssgadapter and build with Deno:Sometimes (not everytime) Rollup fails with this:
Full build log
useTask$with promises has same problem too.System Info
System: OS: Linux 6.19 Debian GNU/Linux forky/sid CPU: (16) x64 AMD Eng Sample: 100-000000300-40_Y Memory: 17.32 GB / 30.75 GB Container: Yes Shell: 5.3.9 - /usr/bin/bash Binaries: Node: 25.6.1 - /opt/app/node/current/bin/node npm: 11.9.0 - /opt/app/node/current/bin/npm bun: 1.3.11 - /opt/app/bun-linux-x64/bun Deno: 2.7.12 - /opt/app/deno Browsers: Chromium: 146.0.7680.177 Firefox: 140.9.0esr Firefox Developer Edition: 140.9.0esr * My system isn’t a container, but a minimal Debian system installed with `debootstrap`. It shouldn’t matter anyway ;)Additional Information
The problem is very possibly upstream (of Deno or Vite/Rollup), but given their complexity, I don’t have time to verify it.
I suspect these code in Rollup around the given
node_modules/rollup/dist/es/shared/node-entry.js:23313:28:Probably
Promise.race(or the event loop) behavior differs in Deno? I’m wondering if we can have migrations in qwik codebase.It’s unknown if the problem will persist after the Rolldown migration (#8379).
The reproduction url contains code, but the environment only has node.js 18. If possible, verify locally with Deno, try running
deno task buildmay times (like more than 5).EDIT:
useTask$(() => { new Promise(...); return void 0; });is anti-pattern, should always return the promise(s).