Repository navigation
Angular Universal's serializeApplication can return a promise that never resolves/rejects #296
Description
Title
Error in Angular 2 template provides cryptic error message in case of server side prerender.
Functional impact
If prerender is turned on (like in aspnetcore-spa template), the small typo in the default page Angular 2 template make the whole application fail with cryptic error message.
The same code in browser (w/o prerender) shows the page and descriptive errors in console.
Minimal repro steps
- Create new 'test' app using
yo aspnetcore-spa, choose 'Angular 2' as the framework - Edit routes.ts, setting fetch-data as default redirect
- Edit fetch-data.html, making an error (e.g. change {{ forecast. summary }} to {{ test.summary }}
- Run the app
Expected result
Navigation menu is shown along with the error message that template is errorneous
Actual result
Page states that "Error.
An error occurred while processing your request."
Log contains cryptic error messages like "
info: Microsoft.AspNetCore.Server.Kestrel[14]
Connection id "0HKUKLGUN54V8" communication error
Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException: Error -4081 ECANCELED operation canceled
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0]
An unhandled exception has occurred: A task was canceled.
System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable1.ConfiguredTaskAwaiter.GetResult() at System.Net.Http.HttpClient.<FinishSendAsync>d__58.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.NodeServices.HostingModels.HttpNodeInstance.d__71.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance.d__121.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.NodeServices.NodeServicesImpl.d__91.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.SpaServices.Prerendering.PrerenderTagHelper.d__28.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at AspNetCore._Views_Home_Index_cshtml.d__32.MoveNext() in /Views/Home/Index.cshtml:line 2
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.ViewResult.d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__29.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.d__6.MoveNext()"
Further technical details
The repository contains code to reproduce the error: ysilvestrov/yo-aspnetcore-spa-test@7b14cd6
Looks like it's due to prerender and nodeservices, as if not set the "fetch-data" as a default route, app works, and the angular errors are shown in console.
Activity
SteveSandersonMS commentedon Sep 7, 2016
Thanks for reporting this. It looks like an issue inside the version of
angular-universalthat the templates are currently using. That is, with the kind of coding error in your example, Universal'sserializeApplicationAPI returns a promise that never resolves or rejects. So we just wait for it until a lower-level part of ASP.NET times everything out (hence the message about "task was cancelled").Once we update to a newer build of
angular-universal(waiting on #257, which in turn is waiting on universal-511), I'll try your repro again and see if the same problem still exists.SteveSandersonMS commentedon Sep 8, 2016
I've also now added logic to catch prerendering timeouts and give a more descriptive message (now instead of a generic TaskCancelledException, you'll get a NodeInvocationException that says that your prerendering boot function returned a promise that never resolved or rejected).
[-]Error in template provides cryptic error message in case of server side prerender[/-][+]Angular Universal's serializeApplication can return a promise that never resolves/rejects[/+]MarkPieszak commentedon Sep 8, 2016
Nicely done @SteveSandersonMS ! 👍
One of my goals is to add better Error handling within Universal itself in the future. Hopefully that helps for other scenarios as well :)
SteveSandersonMS commentedon Sep 21, 2016
This issue no longer repros with latest version of angular-universal.