angular: NodeInvocationException: Uncaught (in promise): Error: Injector has already been destroyed. Error: Injector has already been destroyed.

🐞 bug report

Affected Package

The issue is caused by package @angular/platform-server

Is this a regression?

Yes, the previous version in which this bug was not present was: 8

Description

I am using Angular Universal with .net core 2.2 and after migrating to Angular 9 I have this weird issue that on first website load (it does not matter what page) the SSR works perfectly but after navigation to another page and then refreshing I get this error, if I refresh again the websites work without SSR.

removing the Destroy of NgModuleRef instance solves the problem.

This is my code for the main.server.ts

import '@angular/localize/init';
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { INITIAL_CONFIG, platformDynamicServer, PlatformState } from '@angular/platform-server';
import { APP_BASE_HREF } from '@angular/common';
import { enableProdMode, ApplicationRef, NgZone } from '@angular/core';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';
import { SSRResponseStatusCodeService } from './app/services/SSRResponseStatusCode.service';
import { first } from 'rxjs/operators';
import * as cache from 'memory-cache';
export { AppServerModule } from './app/app.server.module';

enableProdMode();

export default createServerRenderer(params => {
	const { AppServerModule, AppServerModuleNgFactory, LAZY_MODULE_MAP } = (module as any).exports;


	const providers = [
		provideModuleMap(LAZY_MODULE_MAP),
		{ provide: INITIAL_CONFIG, useValue: { document: params.data.originalHtml, url: params.url } },
		{ provide: APP_BASE_HREF, useValue: params.baseUrl },
		{ provide: 'BASE_URL', useValue: params.origin + params.baseUrl }
	];

	const cachedEntry = cache.get(params.url);
	if (cachedEntry) {
		return new Promise<RenderResult>((resolve) => {
			resolve(cachedEntry);
		})
	}

	const renderPromise = AppServerModuleNgFactory
		? /* AoT */ platformDynamicServer(providers).bootstrapModuleFactory(AppServerModuleNgFactory)
		: /* dev */ platformDynamicServer(providers).bootstrapModule(AppServerModule);

	return renderPromise.then(moduleRef => {
		const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
		const state = moduleRef.injector.get(PlatformState);
		const zone = moduleRef.injector.get(NgZone);

		// this will get the instance of the HttpStatusCodeService created for this request.
		const statusCodeService = moduleRef.injector.get(SSRResponseStatusCodeService);

		return new Promise<RenderResult>((resolve, reject) => {
			zone.onError.subscribe((errorInfo: any) => reject(errorInfo));
			appRef.isStable.pipe(first(isStable => isStable))
				.subscribe(() => {
					// Because 'onStable' fires before 'onError', we have to delay slightly before
					// completing the request in case there's an error to report
					setImmediate(() => {
						const result = {
							html: state.renderToString(),
							// this will get the currently set status code and return it along with the prerendered html string
							statusCode: statusCodeService.getStatusCode()
						}
						cache.put(params.url, result, 20 * 60 * 1000);
						resolve(result);
                                                //REMOVING this destroy will solve the problem for angular 9
						moduleRef.destroy();
					});
				});
		});
	});
});

🔥 Exception or Error


NodeInvocationException: Uncaught (in promise): Error: Injector has already been destroyed. Error: Injector has already been destroyed.

🌍 Your Environment

Angular Version:


Angular CLI: 9.1.9
Node: 12.13.1
OS: win32 x64

Angular: 9.1.11
... animations, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, platform-server, router
Ivy Workspace: Yes

Package                                    Version
--------------------------------------------------------------------
@angular-devkit/architect                  0.901.9
@angular-devkit/build-angular              0.901.9
@angular-devkit/build-optimizer            0.901.9
@angular-devkit/build-webpack              0.901.9
@angular-devkit/core                       9.1.9
@angular-devkit/schematics                 9.1.9
@angular/cdk                               9.2.4
@angular/cli                               9.1.9
@angular/flex-layout                       9.0.0-beta.31
@angular/material                          9.2.4
@ngtools/webpack                           9.1.9
@nguniversal/aspnetcore-engine             9.1.1
@nguniversal/builders                      9.1.1
@nguniversal/common                        9.1.1
@nguniversal/express-engine                9.1.1
@nguniversal/module-map-ngfactory-loader   8.2.6
@schematics/angular                        9.1.9
@schematics/update                         0.901.9
rxjs                                       6.5.5
typescript                                 3.8.3
webpack                                    4.43.0

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 21 (12 by maintainers)

Most upvoted comments

wait what about those of us not relying on a .net SSR solution…

Thanks @naveedahmed1, I can replicate the issue with the replication provided. I can also see that there were some changes on the dotnet side were using globals is no longer possible and html must return the complete page because of the below error.

InvalidOperationException: Globals is not supported when prerendering via UseSpaPrerendering().
Instead, your prerendering logic should return a complete HTML page, in which you embed any information you wish to return to the client.

I can confirm that some fixes need to be done in @nguniversal/aspnetcore-engine. (I’ll be landing a fix in the next couple of days). I suggest to subscribe to angular/universal#1808 to keep yourself up-to-date.

@CL-BayanAbuawad, I still need to take a look at your reproduction, which I will do in the next day or two.

I can confirm the problem for angular 11. The error happens occasionally.

Thank you so much @alan-agius4 for the update, I really appreciate your time and efforts 😃

I have also subscribed to https://github.com/angular/universal/issues/1808

@alan-agius4 I have added you to the repo, just clone the repo, restore dependencies and run project by pressing F5. If you see error AggregateException: One or more errors occurred. (The NPM script 'build:ssr' exited without indicating success....) this is a know issue in .Net Core, try pressing F5 few time and it should start working.

Please comment out the code in ClientApp/src/main.server.ts and uncomment the code block at the bottom of the same file.

same issue here after angular 9+ ’ Injector has already been destroyed’ (only in ssr)

Same problem in Angular 9 and 10 project at Server Side Rendering. When I extend the BaseComponent which has an injector.get() in the contrustor, If frequently visit the server side rendering page, ocassionally will throw the error “Uncaught (in promise): Error: Injector has already been destroyed.” ng

@pkozlowski-opensource thanks for your replay, I will work on one soon