next.js
60f903c7 - Improve webpack loader error messages and handling (#89698)

Commit
51 days ago
Improve webpack loader error messages and handling (#89698) ## What? This PR improves error reporting for webpack loaders by: 1. **Preserving loader paths in error messages**: Modified the webpack message formatter to rewrite "Module build failed" headers to preserve the loader path information while removing the verbose prefix. This makes errors more readable in both CLI output and error overlays. 2. **Better error wrapping for non-Error throws**: When loaders throw non-Error values (strings, objects, etc.), the error is now wrapped with loader path information in the stack trace, making it easier to identify which loader caused the error. 3. **Catching deferred loader errors**: Added handling for errors that occur after loader completion (e.g., unhandled Promise rejections, setTimeout throws) by: - Adding an `unhandledRejection` handler in the IPC layer - Delaying resolution in webpack-loaders transform to allow error handlers to fire before sending the 'end' message 4. **Conditional `(from ...)` annotation**: The `(from /path/to/loader.js)` annotation is only added when the loader path is **not already visible** in the error's stack trace. This avoids redundant noise for errors that already include the loader in their stack, while still providing the annotation for errors without loader context (string throws, errors without stacks, etc.). 5. **Hiding internal Next.js loader paths**: Internal Next.js loader paths (under `next/dist/`) are filtered from error messages since they're noise for users. Only user-authored loader paths are shown. 6. **Comprehensive test coverage**: Added e2e tests covering various error scenarios (Error throws, string throws, Promise rejections, setTimeout errors, no-stack errors, filesystem errors) with verification of both CLI output and error overlay display. ## Why? Webpack loader errors were previously difficult to debug because: - The verbose "Module build failed" prefix obscured the actual error message - Non-Error throws lost their context and loader information - Deferred errors (Promise rejections, async throws) were not properly surfaced - Error overlays didn't clearly show which loader caused the problem - The `(from ...)` annotation was always added, even when the loader path was already in the stack trace (addressed per review feedback) ## How? - **format-webpack-messages.ts**: Changed from filtering out loader headers to rewriting them, preserving the `(from ./loaders/...)` information. Internal Next.js loader paths are hidden. - **webpack-loaders.ts**: Added error wrapping for non-Error values, deferred resolution to catch async errors, and conditional `(from ...)` annotation that checks `err.stack` before appending. Resolves loader paths into an array, then checks if any path appears in the stack before deciding to annotate. - **ipc/index.ts**: Added `unhandledRejection` handler to surface Promise-related errors. - **Test loaders**: `error-loader.js` and `fs-error-loader.js` delegate to a `create-error.js` helper that creates errors and invokes the loader callback inside `setTimeout`. This ensures the loader file path is absent from the stack trace, exercising the conditional `(from ...)` annotation path. Other loaders (string-error, promise-error, timeout-error, no-stack-error) test different error scenarios directly. - **Test suite**: Comprehensive e2e tests verify CLI output and error overlay for each error type. Turbopack-specific tests cover promise rejections, timeout errors, no-stack errors, and filesystem errors. --------- Co-authored-by: Claude <noreply@anthropic.com>
Author
Parents
Loading