fix(router): honor routeLoader$ id option to avoid wrapper id collisions#8749
Merged
wmertens merged 6 commits intoJun 19, 2026
Merged
Conversation
Loaders created through a shared wrapper that passes an inline QRL to routeLoader$ all share one optimizer-assigned hash, so they collided on the same __id and all but the first were deduped away in getModuleRouteLoaders. Honor the (previously deprecated) id option so each loader can pass a distinct id (e.g. fn.getHash()), and warn in dev when two loaders share an id.
🦋 Changeset detectedLatest commit: 208628f The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@qwik.dev/core
@qwik.dev/router
eslint-plugin-qwik
create-qwik
@qwik.dev/optimizer
commit: |
Contributor
built with Refined Cloudflare Pages Action⚡ Cloudflare Pages Deployment
|
a15f452 to
58f59c9
Compare
58f59c9 to
281c656
Compare
wmertens
approved these changes
Jun 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Overview
Loaders defined through a shared wrapper that passes an inline QRL to
routeLoader$— e.g. awithErrorHandling(fn)helper — all share a single optimizer-assigned QRL hash. Since the loader id was derived solely from that hash (loader.__id = loaderQrl.getHash()), every wrapped loader collided on the same__id, and all but the first were silently deduped away ingetModuleRouteLoaders. The result: only one of the wrapped loaders ran during SSR and SPA navigation. PlainrouteLoader$calls are unaffected because each is its own lexical QRL with a distinct hash.Changes
idoption (previously marked@deprecated Unused):loader.__id = id ?? loaderQrl.getHash(). Wrappers can now pass a stable, distinct id such asfn.getHash().getModuleRouteLoaderswhen two distinct loaders share the same id, so this collision surfaces loudly instead of silently dropping loaders.idoption and added a changeset.Notes
Surfaced while migrating a real app to Qwik v2: a
routeLoaderWithErrorHandlinghelper wrappingrouteLoader$caused only the first loader on each route to run. The app already passedid: fn.getHash(), but the router had stopped honoring it.I couldn't run the router unit tests in my environment; happy to add a
getModuleRouteLoadersdedup/id-override test if you'd like.