Qwik optimizer error in useVisibleTask$ / component$ in CI
The Qwik optimizer rewrites every $ boundary (component$, useVisibleTask$, event handlers) into lazy-loadable QRLs. It errors during build when a boundary captures a reference it cannot hoist, such as a value declared after use or an import used incorrectly.
What this error means
A qwik build step fails with a Qwik optimizer error referencing a $ symbol, or "Reference to identifier ... can not be used inside a QRL", pointing at a useVisibleTask$/component$.
[Qwik Optimizer Error]
Reference to identifier "config" can not be used inside a "useVisibleTask$()"
since it is a captured value that is not exported or serializable.
src/components/Chart.tsx:14Common causes
A captured identifier the optimizer cannot hoist
The $ boundary references a local that is neither exported nor serializable, so the optimizer cannot produce a lazy chunk.
Browser-only work in the wrong task
Using useTask$ (runs on server) for DOM work, instead of useVisibleTask$ (client only), captures browser refs on the server.
How to fix it
Fix the capture and pick the right task
- Move DOM/browser work into
useVisibleTask$, which runs only in the browser. - Reference only serializable state or props inside the boundary.
- Import shared helpers at module top level so the optimizer can resolve them.
import { component$, useVisibleTask$, useSignal } from '@builder.io/qwik';
export default component$(() => {
const ref = useSignal<HTMLDivElement>();
useVisibleTask$(() => {
ref.value?.focus(); // browser only, runs client side
});
return <div ref={ref} />;
});Keep helpers importable
Define shared functions/constants at module scope and import them, so the optimizer hoists a QRL rather than failing on a local capture.
How to prevent it
- Use
useVisibleTask$for browser-only side effects. - Capture only serializable values inside
$boundaries. - Enable
eslint-plugin-qwikto catch invalid captures pre-CI.