-
Notifications
You must be signed in to change notification settings - Fork 1
fix(server): handle unhandledRejection and catch sync SSR error #322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
…void crashes Add a global handler for unhandled promise rejections during SSR to log and prevent the server from crashing on common HTTP errors. Wrap loadOnServer in a try/catch to handle synchronous errors (e.g. superagent 404) and route them to the existing error handler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds error handling for unhandled promise rejections and synchronous errors during server-side rendering to prevent server crashes when encountering HTTP errors like 404s.
- Adds a global
unhandledRejectionevent handler to prevent server crashes on API errors - Wraps the
loadOnServercall in try-catch to handle synchronous errors from superagent - Includes minor code formatting improvements for readability
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
- add original tests & snapshots plus the test for array being based within href
…SSR error handler with detailed logging - This is to take into consideration the feedback of Github copilot
…void errors when url is undefined - If url is falsy and isExternal is false (now guaranteed by your change on line 82), line 87 will throw a TypeError when attempting to call .includes() on a falsy value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/customizations/volto/components/manage/UniversalLink/UniversalLink.jsx
Outdated
Show resolved
Hide resolved
…rors on undefined href
…w, structure, build/test, coding & testing, PRs, security)
…re and Dependencies sections
…e page-document area
…rollHeight; update test - Convert waitForAllContentToLoad to async/await with try/catch to properly wait for iframes, images and Plotly charts before printing - Use pageDocument.scrollHeight for the final scroll to ensure the correct container is scrolled - Update test to repeatedly flush timers/promises and assert window.scrollTo includes behavior: 'instant'
- to be able to call individual tests and properly collect coverage
…otly charts, media events, scrolling and timeout/error cases
Add createMockStore, defaultProps and renderWidget test helpers and extend coverage for UserSelectWidget. New tests cover normalization variants (normalizeChoices / normalizeSingleSelectOption), rendering with initial vocabulary state, choice updates, async search interactions (focus/change, noOptionsMessage, clearing selection), lifecycle behaviors (timeouts/unmount, terms cache update), disabled/placeholder states and MenuList handling for large choice sets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
jest-addon.config.js
Outdated
| fs.existsSync( | ||
| path.join( | ||
| __dirname, | ||
| 'node_modules', | ||
| '@eeacms', | ||
| addonName, | ||
| 'jest.setup.js', | ||
| ), | ||
| ) | ||
| ? `<rootDir>/node_modules/@eeacms/${addonName}/jest.setup.js` | ||
| : `<rootDir>/src/addons/${addonName}/jest.setup.js`, | ||
| ], |
Copilot
AI
Oct 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The nested path.join calls create complex logic. Consider extracting the path construction to a variable for better readability and maintainability.
| fs.existsSync( | |
| path.join( | |
| __dirname, | |
| 'node_modules', | |
| '@eeacms', | |
| addonName, | |
| 'jest.setup.js', | |
| ), | |
| ) | |
| ? `<rootDir>/node_modules/@eeacms/${addonName}/jest.setup.js` | |
| : `<rootDir>/src/addons/${addonName}/jest.setup.js`, | |
| ], | |
| (() => { | |
| const nodeModulesSetupPath = path.join( | |
| __dirname, | |
| 'node_modules', | |
| '@eeacms', | |
| addonName, | |
| 'jest.setup.js', | |
| ); | |
| return fs.existsSync(nodeModulesSetupPath) | |
| ? `<rootDir>/node_modules/@eeacms/${addonName}/jest.setup.js` | |
| : `<rootDir>/src/addons/${addonName}/jest.setup.js`; | |
| })(), |
jest-addon.config.js
Outdated
| const s = fs.statSync(p); | ||
| statCache.set(p, s); | ||
| return s; | ||
| } catch { |
Copilot
AI
Oct 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getStatSync function returns null on error but doesn't provide any context about what failed. Consider logging or documenting why the stat call failed for debugging purposes.
| } catch { | |
| } catch (err) { | |
| console.error(`[getStatSync] Failed to stat path: ${p}\nError: ${err && err.message ? err.message : err}`); |
src/customizations/volto/server.jsx
Outdated
| function errorHandler(error) { | ||
| // Log error details for debugging | ||
| const ignoredErrors = [301, 302, 401, 404]; |
Copilot
AI
Oct 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ignoredErrors array is defined inside the errorHandler function, causing it to be recreated on every error. Move this constant outside the function for better performance.
| function errorHandler(error) { | |
| // Log error details for debugging | |
| const ignoredErrors = [301, 302, 401, 404]; | |
| const ignoredErrors = [301, 302, 401, 404]; | |
| function errorHandler(error) { | |
| // Log error details for debugging |
- as suggested by Copilot
…hat logic to 291995_improve_pdf_printing
|
⏺ PR Review Summary Based on my analysis of the changes in this branch compared to develop, here's my assessment: ✅ SAFE TO MERGE - These are defensive bug fixes with good test coverage Key Changes
File: src/customizations/volto/components/manage/UniversalLink/UniversalLink.jsx Changes:
Safety Assessment:
File: src/customizations/volto/components/manage/UniversalLink/UniversalLink.test.jsx Test Coverage:
Safety Assessment:
File: src/customizations/volto/server.jsx Changes:
Safety Assessment:
New documentation file - no runtime impact. Potential Issues & Risk Assessment
✅ No Breaking Changes Detected
Backward Compatibility Analysis Scenarios Tested:
Migration Impact: NONE No changes required in consuming code. Production Safety Checklist
Final Recommendation 🟢 APPROVED FOR PRODUCTION Reasoning:
Risk Level: VERY LOW The changes actually reduce crash risk significantly by:
Suggested Actions Before Deploy:
This PR is a textbook example of defensive programming and crash prevention. Strong approve for production deployment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 9 comments.
Comments suppressed due to low confidence (1)
src/customizations/volto/server.jsx:201
- If the
errorHandlerfunction itself throws an error (e.g., ifrenderToStringfails orres.sendthrows), there's no safety net to prevent the request from hanging. Consider wrapping the errorHandler's operations in a try-catch block and sending a minimal error response as a last resort to ensure the client always receives a response.
function errorHandler(error) {
// Log error details for debugging
if (!ignoredErrors.includes(error.status)) {
console.error('[SSR Error Handler]', {
url: req.url,
status: error.status,
message: error.message,
stack: error.stack,
});
} else {
// Log ignored errors at debug level
console.log('[SSR Error Handler] HTTP error:', {
url: req.url,
status: error.status,
message: error.message,
});
}
// Render error page
const errorPage = (
<Provider store={store} onError={reactIntlErrorHandler}>
<StaticRouter context={{}} location={req.url}>
<ErrorPage message={error.message} />
</StaticRouter>
</Provider>
);
res.set({
'Cache-Control': 'public, max-age=60, no-transform',
});
res
.status(error.status || 500) // If error happens in Volto code itself error status is undefined
.send(`<!doctype html> ${renderToString(errorPage)}`);
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| const isExternal = !isInternalURL(url); | ||
| const isExternal = url ? !isInternalURL(url) : false; |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good defensive programming to check if url is truthy before calling isInternalURL(url). However, consider what should happen when url is falsy. Currently isExternal will be false, which means the code will attempt to render a Link component with a falsy URL. This could lead to unexpected behavior. Consider adding an early return or additional validation when url is null/undefined/empty.
| config.settings.externalRoutes = [ | ||
| { | ||
| match: { | ||
| path: '/external-app', | ||
| exact: true, | ||
| strict: false, | ||
| }, | ||
| url(payload) { | ||
| return payload.location.pathname; | ||
| }, | ||
| }, | ||
| ]; |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifying config.settings.externalRoutes globally in tests can cause test pollution and flaky tests if tests run in parallel or if the config state persists between tests. Consider storing the original value in a beforeEach hook and restoring it in an afterEach hook, or use a test-specific mock of the config object.
src/customizations/volto/components/manage/UniversalLink/UniversalLink.test.jsx
Show resolved
Hide resolved
src/customizations/volto/components/manage/UniversalLink/UniversalLink.test.jsx
Outdated
Show resolved
Hide resolved
src/customizations/volto/components/manage/UniversalLink/UniversalLink.test.jsx
Outdated
Show resolved
Hide resolved
src/customizations/volto/components/manage/UniversalLink/UniversalLink.test.jsx
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <[email protected]>
I have an error at
http://localhost:3000/en/sandbox/david-tests.
When trying to visit:
http://localhost:3000/en/sandbox/david-tests/contents
the superagent code crashed which meant I couldn't navigate any other pages anymore.
This pr adds a scoped request handler for unhandled promise rejections during SSR to log and prevent the server from crashing on common HTTP errors. Wrap loadOnServer in a try/catch to handle synchronous errors (e.g. superagent 404) and route them to the existing error handler.
This pull request introduces improvements to the
UniversalLinkcomponent and its test coverage, as well as adds a comprehensive repository guidelines document. The most significant changes are the robust handling of invalidhrefvalues inUniversalLink, expanded unit tests for bothUniversalLinkandUserSelectWidget, and the addition of clear documentation for repository usage and development.UniversalLink Improvements
UniversalLinkto detect and handle cases wherehrefis an array instead of a string, logging an error and rendering nothing to prevent runtime errors.urlvalues.Test Coverage Enhancements
UniversalLinkinUniversalLink.test.jsx, covering internal/external links, attribute handling, blacklisted URLs, error cases, and invalidhrefscenarios.UniversalLinktest cases.UserSelectWidgetto cover Redux state integration, prop variations, selection clearing, async behavior, and normalization logic. [1] [2]fireEventimport for user interaction simulation inUserSelectWidgettests.Documentation
AGENTS.mdfile outlining repository structure, coding standards, dependencies, build/test procedures, and security/configuration guidelines for contributors.