Skip to content

feat: use error cause to simplify the error msg of lazy bundle loading#2056

Merged
upupming merged 1 commit intomainfrom
feat/lazy-bundle-error-cause
Dec 29, 2025
Merged

feat: use error cause to simplify the error msg of lazy bundle loading#2056
upupming merged 1 commit intomainfrom
feat/lazy-bundle-error-cause

Conversation

@upupming
Copy link
Copy Markdown
Collaborator

@upupming upupming commented Dec 25, 2025

Summary by CodeRabbit

  • Bug Fixes
    • Improved error handling for lazy bundle loading failures. Errors now preserve complete information through enhanced cause chains, providing better error context for debugging and tracking issues.

✏️ Tip: You can customize this high-level summary in your review settings.

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).
  • Changeset added, and when a BREAKING CHANGE occurs, it needs to be clearly marked (or not required).

@upupming upupming requested review from HuJean and hzy as code owners December 25, 2025 11:46
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Dec 25, 2025

🦋 Changeset detected

Latest commit: 53aaa03

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@lynx-js/react Patch

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 25, 2025

📝 Walkthrough

Walkthrough

The PR updates error handling in lazy bundle loading by replacing the source error detail field with schema and implementing an error.cause pattern to preserve the original result structure for downstream error handling. Changes span the implementation, tests, and changeset documentation.

Changes

Cohort / File(s) Summary
Lazy bundle error handling updates
.changeset/new-beans-warn.md, packages/react/runtime/src/lynx/lazy-bundle.ts, packages/react/runtime/__test__/lynx/lazy-bundle.test.js
Refactored error handling to use error.cause for preserving original result; replaced error detail field from source to schema; updated test expectations and added new test case validating error cause structure and promise rejection behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

framework:React

Suggested reviewers

  • HuJean
  • hzy

Poem

🐰 Errors now carry their cause with grace,
Schema fields take source's place,
With cause preserved in structured care,
Lazy bundles load beyond compare!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: use error cause to simplify the error msg of lazy bundle loading' accurately describes the main change, which restructures error handling in lazy bundle loading to use error.cause for exposing the original result while simplifying the error message.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/lazy-bundle-error-cause

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
.changeset/new-beans-warn.md (1)

5-19: Consider clarifying that error.cause is a JSON string.

The documentation correctly demonstrates accessing error.cause, but users might benefit from knowing it's a stringified JSON that can be parsed. Consider adding a note or example showing:

const result = JSON.parse(error.cause);
console.error(`Failed with code: ${result.code}`);

This would help users understand they can extract structured data from the cause.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd89bf9 and 53aaa03.

📒 Files selected for processing (3)
  • .changeset/new-beans-warn.md
  • packages/react/runtime/__test__/lynx/lazy-bundle.test.js
  • packages/react/runtime/src/lynx/lazy-bundle.ts
🧰 Additional context used
📓 Path-based instructions (1)
.changeset/*.md

📄 CodeRabbit inference engine (AGENTS.md)

For contributions, generate and commit a Changeset describing your changes

Files:

  • .changeset/new-beans-warn.md
🧠 Learnings (15)
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, private packages (marked with "private": true in package.json) like lynx-js/react-transform don't require meaningful changeset entries even when their public APIs change, since they are not published externally and only affect internal development.

Applied to files:

  • .changeset/new-beans-warn.md
  • packages/react/runtime/src/lynx/lazy-bundle.ts
📚 Learning: 2025-08-07T04:00:59.645Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1454
File: pnpm-workspace.yaml:46-46
Timestamp: 2025-08-07T04:00:59.645Z
Learning: In the lynx-family/lynx-stack repository, the webpack patch (patches/webpack5.101.0.patch) was created to fix issues with webpack5.99.9 but only takes effect on webpack5.100.0 and later versions. The patchedDependencies entry should use "webpack@^5.100.0" to ensure the patch applies to the correct version range.

Applied to files:

  • .changeset/new-beans-warn.md
📚 Learning: 2025-09-12T09:43:04.847Z
Learnt from: gaoachao
Repo: lynx-family/lynx-stack PR: 1736
File: .changeset/spotty-experts-smoke.md:1-3
Timestamp: 2025-09-12T09:43:04.847Z
Learning: In the lynx-family/lynx-stack repository, empty changeset files (containing only `---\n\n---`) are used for internal changes that modify src/** files but don't require meaningful release notes, such as private package changes or testing-only modifications. This satisfies CI requirements without generating user-facing release notes.

Applied to files:

  • .changeset/new-beans-warn.md
📚 Learning: 2025-08-19T11:25:36.127Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1558
File: .changeset/solid-squids-fall.md:2-2
Timestamp: 2025-08-19T11:25:36.127Z
Learning: In the lynx-family/lynx-stack repository, changesets should use the exact package name from package.json#name, not generic or unscoped names. Each package has its own specific scoped name (e.g., "lynx-js/react-transform" for packages/react/transform).

Applied to files:

  • .changeset/new-beans-warn.md
  • packages/react/runtime/src/lynx/lazy-bundle.ts
📚 Learning: 2025-08-21T08:46:54.494Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1370
File: packages/webpack/cache-events-webpack-plugin/src/LynxCacheEventsRuntimeModule.ts:23-27
Timestamp: 2025-08-21T08:46:54.494Z
Learning: In Lynx webpack runtime modules, the team prioritizes performance and simplicity over defensive runtime error handling. They prefer relying on compile-time type safety (TypeScript) rather than adding runtime checks like try-catch blocks or type validation, especially for performance-critical code like cache event setup/cleanup functions.

Applied to files:

  • .changeset/new-beans-warn.md
  • packages/react/runtime/src/lynx/lazy-bundle.ts
  • packages/react/runtime/__test__/lynx/lazy-bundle.test.js
📚 Learning: 2025-09-25T14:03:25.576Z
Learnt from: PupilTong
Repo: lynx-family/lynx-stack PR: 1834
File: packages/web-platform/web-worker-runtime/src/backgroundThread/background-apis/createChunkLoading.ts:162-171
Timestamp: 2025-09-25T14:03:25.576Z
Learning: In the lynx-stack codebase, for loadScriptAsync implementations in createChunkLoading.ts, unhandled promise rejections from readScriptAsync are intentionally not caught - the caller is expected to handle errors rather than the loadScriptAsync method itself invoking the callback with error messages.

Applied to files:

  • .changeset/new-beans-warn.md
  • packages/react/runtime/src/lynx/lazy-bundle.ts
  • packages/react/runtime/__test__/lynx/lazy-bundle.test.js
📚 Learning: 2025-08-27T12:42:01.095Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1616
File: packages/webpack/cache-events-webpack-plugin/test/cases/not-cache-events/lazy-bundle/index.js:3-3
Timestamp: 2025-08-27T12:42:01.095Z
Learning: In webpack, properties like __webpack_require__.lynx_ce are injected during compilation/build time when webpack processes modules and generates bundles, not at runtime when dynamic imports execute. Tests for such properties don't need to wait for dynamic imports to complete.

Applied to files:

  • .changeset/new-beans-warn.md
  • packages/react/runtime/src/lynx/lazy-bundle.ts
  • packages/react/runtime/__test__/lynx/lazy-bundle.test.js
📚 Learning: 2025-07-22T09:23:07.797Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:23:07.797Z
Learning: In the lynx-family/lynx-stack repository, changesets are only required for meaningful changes to end-users such as bugfixes and features. Internal/development changes like chores, refactoring, or removing debug info do not need changeset entries.

Applied to files:

  • .changeset/new-beans-warn.md
📚 Learning: 2025-07-22T09:26:16.722Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1330
File: .changeset/olive-animals-attend.md:1-3
Timestamp: 2025-07-22T09:26:16.722Z
Learning: In the lynx-family/lynx-stack repository, CI checks require changesets when files matching the pattern "src/**" are modified (as configured in .changeset/config.json). For internal changes that don't need meaningful changesets, an empty changeset file is used to satisfy the CI requirement while not generating any release notes.

Applied to files:

  • .changeset/new-beans-warn.md
📚 Learning: 2025-08-13T11:46:43.737Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1523
File: vitest.config.ts:5-6
Timestamp: 2025-08-13T11:46:43.737Z
Learning: In the lynx-stack codebase, default imports are consistently used for Node.js built-in modules (e.g., `import os from 'node:os'`, `import fs from 'node:fs'`). The TypeScript configuration supports esModuleInterop and allowSyntheticDefaultImports, making default imports the preferred pattern over namespace imports for Node.js built-ins.

Applied to files:

  • .changeset/new-beans-warn.md
📚 Learning: 2025-11-04T10:15:14.965Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/runtime/__test__/snapshotPatch.test.jsx:725-749
Timestamp: 2025-11-04T10:15:14.965Z
Learning: In packages/react/runtime/src/snapshot.ts, the snapshotCreatorMap type signature uses `Record<string, (uniqId: string) => string>` (returning string) rather than void for backward compatibility. Old lazy bundles still use the pattern `const snapshot_xxx = createSnapshot(...)` directly, which requires createSnapshot to return a value. The snapshotCreatorMap creators that wrap createSnapshot calls must maintain the same return type to support these legacy bundles.

Applied to files:

  • packages/react/runtime/src/lynx/lazy-bundle.ts
  • packages/react/runtime/__test__/lynx/lazy-bundle.test.js
📚 Learning: 2025-11-06T01:19:23.670Z
Learnt from: colinaaa
Repo: lynx-family/lynx-stack PR: 1917
File: packages/mcp-servers/devtool-mcp-server/tsconfig.json:8-8
Timestamp: 2025-11-06T01:19:23.670Z
Learning: The lynx-js/devtool-mcp-server package in lynx-family/lynx-stack targets Node.js >=18.19 (specified in its package.json engines), which is different from the root project's requirement of Node.js ^22 || ^24. The package uses "lib": ["ES2024.Promise"] in its tsconfig.json because it manually includes polyfills for Promise.withResolvers while maintaining compatibility with Node.js v18.

Applied to files:

  • packages/react/runtime/src/lynx/lazy-bundle.ts
📚 Learning: 2025-09-18T08:12:56.802Z
Learnt from: Sherry-hue
Repo: lynx-family/lynx-stack PR: 1770
File: packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts:316-318
Timestamp: 2025-09-18T08:12:56.802Z
Learning: In packages/web-platform/web-mainthread-apis/src/utils/processStyleInfo.ts, the current implementation uses cardStyleElement.textContent += for lazy component styles. While this could theoretically invalidate rule indices by reparsing the stylesheet, Sherry-hue indicated that UIDs don't repeat for the same element, making this approach acceptable for now. A future optimization to use separate style elements per entry was discussed but deferred to a separate PR to keep the current lazy bundle PR focused.

Applied to files:

  • packages/react/runtime/src/lynx/lazy-bundle.ts
📚 Learning: 2025-10-29T10:28:27.519Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1899
File: packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/lib.rs/should_static_extract_dynamic_inline_style.js:20-24
Timestamp: 2025-10-29T10:28:27.519Z
Learning: Files inside packages/react/transform/crates/swc_plugin_snapshot/tests/__swc_snapshots__/ are auto-generated test snapshot files and should not be manually updated. Any issues with the generated code should be addressed in the code generator/transform logic, not in the snapshots themselves.

Applied to files:

  • packages/react/runtime/__test__/lynx/lazy-bundle.test.js
📚 Learning: 2025-09-23T08:54:39.966Z
Learnt from: upupming
Repo: lynx-family/lynx-stack PR: 1670
File: packages/webpack/css-extract-webpack-plugin/test/hotCases/hot/hot-update-json/dual-thread/__snapshot__/index.css:6-8
Timestamp: 2025-09-23T08:54:39.966Z
Learning: In the lynx-stack CSS extract webpack plugin tests, many test fixture CSS files intentionally use invalid CSS syntax like `color: 'red';` with quoted values. The snapshots correctly reflect this invalid CSS from the source fixtures. To fix CSS validation issues, the source fixture files should be updated first, then snapshots regenerated, rather than manually editing snapshots.

Applied to files:

  • packages/react/runtime/__test__/lynx/lazy-bundle.test.js
🧬 Code graph analysis (1)
packages/react/runtime/__test__/lynx/lazy-bundle.test.js (1)
packages/react/runtime/src/lynx/lazy-bundle.ts (1)
  • loadLazyBundle (64-136)
🔇 Additional comments (4)
packages/react/runtime/src/lynx/lazy-bundle.ts (1)

106-110: LGTM! Error handling improvement aligns with PR objectives.

The implementation correctly simplifies the error message while preserving the full result in error.cause for downstream consumers. The ES5 compatibility workaround using property assignment is appropriate.

packages/react/runtime/__test__/lynx/lazy-bundle.test.js (3)

243-243: Test updates correctly reflect the API change from source to schema.

The detail structure change is consistently applied across test cases.

Also applies to: 450-450


260-260: Error message snapshots updated consistently.

All snapshots now reflect the simplified error message format: Lazy bundle load failed, schema: foo.

Also applies to: 267-267, 465-465, 473-473


488-532: Excellent test coverage for the new error.cause feature.

This test comprehensively validates:

  • Error rejection with the new message format
  • The error.cause property containing the stringified result (line 506-508)
  • Promise chain behavior when catching and processing the error
  • The derived non-error value after error handling (lines 522-523)

The test matches the usage pattern shown in the changeset documentation.

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 25, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Dec 25, 2025

CodSpeed Performance Report

Merging #2056 will not alter performance

Comparing feat/lazy-bundle-error-cause (53aaa03) with main (cd89bf9)

Summary

✅ 63 untouched
⏩ 3 skipped1

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Dec 25, 2025

React Example

#6695 Bundle Size — 237.01KiB (0%).

53aaa03(current) vs cd89bf9 main#6689(baseline)

Bundle metrics  no changes
                 Current
#6695
     Baseline
#6689
No change  Initial JS 0B 0B
No change  Initial CSS 0B 0B
No change  Cache Invalidation 0% 0%
No change  Chunks 0 0
No change  Assets 4 4
No change  Modules 162 162
No change  Duplicate Modules 65 65
No change  Duplicate Code 46.75% 46.75%
No change  Packages 2 2
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#6695
     Baseline
#6689
No change  IMG 145.76KiB 145.76KiB
No change  Other 91.25KiB 91.25KiB

Bundle analysis reportBranch feat/lazy-bundle-error-causeProject dashboard


Generated by RelativeCIDocumentationReport issue

@relativeci
Copy link
Copy Markdown

relativeci Bot commented Dec 25, 2025

Web Explorer

#6855 Bundle Size — 376.4KiB (0%).

53aaa03(current) vs cd89bf9 main#6849(baseline)

Bundle metrics  Change 1 change
                 Current
#6855
     Baseline
#6849
No change  Initial JS 149.87KiB 149.87KiB
No change  Initial CSS 32.4KiB 32.4KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 8 8
No change  Assets 8 8
Change  Modules 231(+0.43%) 230
No change  Duplicate Modules 16 16
No change  Duplicate Code 3.12% 3.12%
No change  Packages 4 4
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#6855
     Baseline
#6849
No change  JS 247.01KiB 247.01KiB
No change  Other 96.98KiB 96.98KiB
No change  CSS 32.4KiB 32.4KiB

Bundle analysis reportBranch feat/lazy-bundle-error-causeProject dashboard


Generated by RelativeCIDocumentationReport issue

Copy link
Copy Markdown
Collaborator

@colinaaa colinaaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@upupming upupming enabled auto-merge (squash) December 26, 2025 11:43
@upupming upupming merged commit 821154b into main Dec 29, 2025
48 checks passed
@upupming upupming deleted the feat/lazy-bundle-error-cause branch December 29, 2025 03:47
colinaaa pushed a commit that referenced this pull request Jan 4, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @lynx-js/gesture-runtime@2.1.1

### Patch Changes

- Add `NativeGesture`
([#2076](#2076))

## @lynx-js/react@0.115.3

### Patch Changes

- Add dual-thread commutation logs for troubleshooting when
`REACT_ALOG=true` or global define `__ALOG__` is set.
([#2081](#2081))

- Use error cause to simplify the error msg of lazy bundle loading. User
can catch the error cause to get the original result:
([#2056](#2056))

    ```ts
    const LazyComponent = lazy(async () => {
      try {
        const mod = await import("./lazy-bundle");
        return mod.default;
      } catch (error) {
console.error(`Lazy Bundle load failed message: ${error.message}`);
        // User can catch the error cause to get the original result
        console.error(`Lazy Bundle load failed result: ${error.cause}`);
        throw error;
      }
    });
    ```

## @lynx-js/rspeedy@0.12.5

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-rsbuild-server-middleware@0.19.4

## @lynx-js/react-rsbuild-plugin@0.12.4

### Patch Changes

-   ([#2051](#2051))

-   Updated dependencies \[]:
    -   @lynx-js/react-alias-rsbuild-plugin@0.12.4
    -   @lynx-js/use-sync-external-store@1.5.0
    -   @lynx-js/react-refresh-webpack-plugin@0.3.4
    -   @lynx-js/react-webpack-plugin@0.7.3

## @lynx-js/testing-environment@0.1.9

### Patch Changes

- Fix duplicated `<page />` elements on body when multiple
`__CreatePage` called.
([#2065](#2065))

## @lynx-js/web-constants@0.19.4

### Patch Changes

- Updated dependencies
\[[`bba05e2`](bba05e2)]:
    -   @lynx-js/web-worker-rpc@0.19.4

## @lynx-js/web-core@0.19.4

### Patch Changes

- Updated dependencies
\[[`bba05e2`](bba05e2)]:
    -   @lynx-js/web-worker-rpc@0.19.4
    -   @lynx-js/web-constants@0.19.4
    -   @lynx-js/web-worker-runtime@0.19.4
    -   @lynx-js/web-mainthread-apis@0.19.4

## @lynx-js/web-elements@0.10.1

### Patch Changes

- feat: implement x-webview component
([#2061](#2061))

- feat: support `recyclable="false"` on `list-item` and enable overflow
visibility
([#2069](#2069))

## @lynx-js/web-mainthread-apis@0.19.4

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-constants@0.19.4

## @lynx-js/web-worker-rpc@0.19.4

### Patch Changes

- Ensure the `default` export entry is last in the package exports map.
([#2075](#2075))

## @lynx-js/web-worker-runtime@0.19.4

### Patch Changes

- Updated dependencies
\[[`bba05e2`](bba05e2)]:
    -   @lynx-js/web-worker-rpc@0.19.4
    -   @lynx-js/web-constants@0.19.4
    -   @lynx-js/web-mainthread-apis@0.19.4

## create-rspeedy@0.12.5



## @lynx-js/react-alias-rsbuild-plugin@0.12.4



## upgrade-rspeedy@0.12.5



## @lynx-js/web-core-server@0.19.4



## @lynx-js/web-rsbuild-server-middleware@0.19.4

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants