-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Dev server crashes on thrown exception in async function #2520
Comments
This series of steps seems implausible to me. It's extremely unlikely that installing any adapter would affect dev mode. Rather, I expect what's happening is that because your example depends on |
I'm closing this since the issue reporting guidelines, which are very explicit about the requirement for a reproduction repo, were not followed |
@benmccann You were right, <script lang="ts">
async function getRandomNumber(throwError: boolean) {
if (throwError) {
throw new Error('error');
} else {
return 'ok';
}
}
// with this line, everything works fine
let promise = getRandomNumber(false);
// with this line, dev server crashes on start
// let promise = getRandomNumber(true);
</script> |
And here's the error log:
Like it says, you should wrap the code in the promise with a try-catch or add a Perhaps SvelteKit could use this: https://nodejs.org/api/process.html#process_event_unhandledrejection |
Hmm. I'm not quite sure how to listen for I tried to put a |
The given example in the repository has a {#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await} Interestingly if I assign the promise in // crashes:
let promise = getRandomNumber(true);
// works:
let promise;
onMount(()=> { promise = getRandomNumber(true); }); |
For a component like {#await Promise.reject('foo')}
a
{:then}
b
{:catch}
c
{/await} the compiler in SSR mode currently produces /* App.svelte generated by Svelte v3.43.0 */
import { create_ssr_component, is_promise } from "svelte/internal";
const App = create_ssr_component(($$result, $$props, $$bindings, slots) => {
return `${(function (__value) {
if (is_promise(__value)) return `
a
`;
return (function () {
return `
b
`;
})(__value);
})(Promise.reject('foo'))}`;
});
export default App; This crashes Node 16 because of the unhandled rejected promise. If we wanted the compiled SSR code to always suppress this (by appeasing Node by making it see the promise as handled) we could make this change in the compiler: diff --git a/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts b/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts
index 6a62f872b..c8b0eeb38 100644
--- a/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts
+++ b/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts
@@ -13,7 +13,10 @@ export default function(node: AwaitBlock, renderer: Renderer, options: RenderOpt
renderer.add_expression(x`
function(__value) {
- if (@is_promise(__value)) return ${pending};
+ if (@is_promise(__value)) {
+ __value.catch(() => {});
+ return ${pending};
+ }
return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value));
}(${node.expression.node})
`); Or, it might be a good idea to only add this |
If we wanted to do that, diff --git a/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts b/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts
index 6a62f872b..36eecf38c 100644
--- a/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts
+++ b/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts
@@ -1,6 +1,6 @@
import Renderer, { RenderOptions } from '../Renderer';
import AwaitBlock from '../../nodes/AwaitBlock';
-import { x } from 'code-red';
+import { b, x } from 'code-red';
export default function(node: AwaitBlock, renderer: Renderer, options: RenderOptions) {
renderer.push();
@@ -13,7 +13,10 @@ export default function(node: AwaitBlock, renderer: Renderer, options: RenderOpt
renderer.add_expression(x`
function(__value) {
- if (@is_promise(__value)) return ${pending};
+ if (@is_promise(__value)) {
+ ${node.catch_node != null && b`__value.catch(() => {});`}
+ return ${pending};
+ }
return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value));
}(${node.expression.node})
`); would only suppress the rejected promise if there was a |
I've created sveltejs/svelte#6789 for the Svelte side of this. We can continue the discussion here about how to deal with other types of unhandled rejections, and whether that ought to be the framework's job or the user's job. |
If the framework were to try and handle it, it would have to be in coordination with adapters, since |
Do we have any sort of an idea of what other serverless hosting environments do when there's an unhandled rejection, and whether they let user code hook into that? |
I have no idea, honestly |
I'm facing this now, and it's supremely annoying - any update, @Rich-Harris, @Conduitry? |
Describe the bug
When an error is thrown in an async function the dev server crashes with the static adapter enabled.
With no adapter, the dev server works just fine.
The static build seems to work just fine as well.
Reproduction
npm run dev
and open browser: everything works finesvelte.config.js
npm run dev
and open browser: dev server crashes with error ⚡npm run build
and open build on webserver: everthing seems to work finenpm run preview
after build: preview server crashes with error as well ⚡Logs
System Info
Severity
annoyance
Additional Information
No response
The text was updated successfully, but these errors were encountered: