question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Maximum call stack size exceeded at Array.map in Login component

See original GitHub issue

Issue type

I’m submitting an issue when I made login (check one with “x”)

  • [x ] bug report
  • feature request
  • question about the decisions made in the repository

Issue description

when I try to make login using the authentication component. The screen is keeping freezer and no any request is made to the backend. when I try many times in the console appear the following error Maximum call stack size exceeded"

errorInNebular

Current behavior:

i have the configuration of authentication using jwt token

Expected behavior:

the ngx-admin must be working using jwt token sending the authorization bearer header to the backend and even update the token when it is revoked.

Steps to reproduce:

  1. I used

Related code:

app.module.ts

`/**

  • @license
  • Copyright Akveo. All Rights Reserved.
  • Licensed under the MIT License. See License.txt in the project root for license information. */ import { BrowserModule } from ‘@angular/platform-browser’; import { BrowserAnimationsModule } from ‘@angular/platform-browser/animations’; import { NgModule, ErrorHandler } from ‘@angular/core’; import { HttpClientModule, HTTP_INTERCEPTORS } from ‘@angular/common/http’; import { CoreModule } from ‘./@core/core.module’; import { ThemeModule } from ‘./@theme/theme.module’; import { AppComponent } from ‘./app.component’; import { AppRoutingModule } from ‘./app-routing.module’; import { NbPasswordAuthStrategy, NbAuthModule, NbAuthJWTToken, NbAuthJWTInterceptor, NbTokenStorage, NbTokenLocalStorage, NB_AUTH_TOKEN_INTERCEPTOR_FILTER } from ‘@nebular/auth’; import {AuthModule} from ‘./auth/auth.module’; import { NbSecurityModule, NbRoleProvider } from ‘@nebular/security’; import { environment } from ‘…/environments/environment’; import { NbChatModule, NbDatepickerModule, NbDialogModule, NbMenuModule, NbSidebarModule, NbToastrModule, NbWindowModule, } from ‘@nebular/theme’; import { AuthGuard } from ‘./auth-guard.service’; import {RoleProvider} from ‘./role.provider’; import { GlobalErrorHandler } from ‘./global-error-handler’; import { ServerErrorInterceptor } from ‘./server-error.interceptor’; @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, BrowserAnimationsModule, HttpClientModule, AppRoutingModule, ThemeModule.forRoot(), NbSidebarModule.forRoot(), NbMenuModule.forRoot(), NbDatepickerModule.forRoot(), NbDialogModule.forRoot(), NbWindowModule.forRoot(), NbToastrModule.forRoot(), NbSecurityModule.forRoot(), NbChatModule.forRoot({ messageGoogleMapKey: ‘AIzaSyA_wNuCzia92MAmdLRzmqitRGvCF7wCZPY’, }), CoreModule.forRoot(), AuthModule, NbAuthModule.forRoot({ strategies: [ NbPasswordAuthStrategy.setup({ name: ‘email’, baseEndpoint: environment.baseUrlApi, token: { class: NbAuthJWTToken, key: ‘token’, // this parameter tells where to look for the token }, login: { endpoint: ‘/users/login’, method: ‘post’, redirect: { success: ‘/page/’, failure: null, // stay on the same page }, }, register: { endpoint: ‘/users/sign-in’, method: ‘post’, }, }), ], forms: {}, }),

], providers: [ AuthGuard, { provide: NbRoleProvider, useClass: RoleProvider }, { provide: ErrorHandler, useClass: GlobalErrorHandler }, { provide: NbTokenStorage, useClass: NbTokenLocalStorage }, { provide: HTTP_INTERCEPTORS, useClass: NbAuthJWTInterceptor, multi: true }, { provide: NB_AUTH_TOKEN_INTERCEPTOR_FILTER, useValue: (req) => { return false }}, { provide: HTTP_INTERCEPTORS, useClass: ServerErrorInterceptor, multi: true }, ], bootstrap: [AppComponent], }) export class AppModule { } `

app-routing.module.ts

`import { ExtraOptions, RouterModule, Routes } from ‘@angular/router’; import { NgModule } from ‘@angular/core’; import {LoginComponent} from ‘./auth/components/login/login.component’; import { AuthGuard } from ‘./auth-guard.service’; import { NbAuthComponent, NbLoginComponent, NbLogoutComponent, NbRegisterComponent, NbRequestPasswordComponent, NbResetPasswordComponent, } from ‘@nebular/auth’;

export const routes: Routes = [ { path: ‘pages’, canActivate: [AuthGuard], // here we tell Angular to check the access with our AuthGuard loadChildren: () => import(‘./pages/pages.module’) .then(m => m.PagesModule), }, { path: ‘auth’, component: NbAuthComponent, children: [ { path: ‘’, component: LoginComponent, }, { path: ‘login’, component: LoginComponent, }, { path: ‘register’, component: NbRegisterComponent, }, { path: ‘logout’, component: NbLogoutComponent, }, { path: ‘request-password’, component: NbRequestPasswordComponent, }, { path: ‘reset-password’, component: NbResetPasswordComponent, }, ], }, { path: ‘’, redirectTo: ‘pages’, pathMatch: ‘full’ }, { path: ‘**’, redirectTo: ‘pages’ }, ];

const config: ExtraOptions = { useHash: false, };

@NgModule({ imports: [RouterModule.forRoot(routes, config)], exports: [RouterModule], }) export class AppRoutingModule { } `

auth-guard.service.ts `import { Injectable } from ‘@angular/core’; import { CanActivate, Router } from ‘@angular/router’; import { NbAuthService } from ‘@nebular/auth’; import { tap } from ‘rxjs/operators’;

@Injectable() export class AuthGuard implements CanActivate {

constructor(private authService: NbAuthService, private router: Router) { }

canActivate() { return this.authService.isAuthenticated() .pipe( tap(authenticated => { if (!authenticated) { this.router.navigate([‘auth/login’]); } }), ); } }`

global-error-handler.ts `import { Injectable } from ‘@angular/core’; import { CanActivate, Router } from ‘@angular/router’; import { NbAuthService } from ‘@nebular/auth’; import { tap } from ‘rxjs/operators’;

@Injectable() export class AuthGuard implements CanActivate {

constructor(private authService: NbAuthService, private router: Router) { }

canActivate() { return this.authService.isAuthenticated() .pipe( tap(authenticated => { if (!authenticated) { this.router.navigate([‘auth/login’]); } }), ); } }`

global-error-handler.ts ` import { ErrorHandler, Injectable, Injector } from ‘@angular/core’; import { HttpErrorResponse } from ‘@angular/common/http’; import { ErrorService } from ‘./@core/services/error.service’; import { LoggingService } from ‘./@core/services/logging.service’; import { NotificationService } from ‘./@core/services/notification.service’;

@Injectable() export class GlobalErrorHandler implements ErrorHandler {

constructor(private injector: Injector) { }

handleError(error: Error | HttpErrorResponse) { const errorService = this.injector.get(ErrorService); const logger = this.injector.get(LoggingService); const notifier = this.injector.get(NotificationService); let message; let stackTrace; if (error instanceof HttpErrorResponse) { // Server error message = errorService.getServerErrorMessage(error); stackTrace = errorService.getServerErrorStackTrace(error); notifier.showError(message); } else { // Client Error message = errorService.getClientErrorMessage(error); notifier.showError(message); } // Always log errors logger.logError(message, stackTrace); console.error(error); } }`

server-error.interceptor.ts `import { Injectable, Injector } from ‘@angular/core’; import { HttpEvent, HttpRequest, HttpHandler, HttpInterceptor, HttpErrorResponse, } from ‘@angular/common/http’; import { Observable, throwError } from ‘rxjs’; import { retry, catchError } from ‘rxjs/operators’; import { Router } from ‘@angular/router’; import { NotificationService } from ‘./@core/services/notification.service’;

@Injectable() export class ServerErrorInterceptor implements HttpInterceptor { constructor(private injector: Injector) {}

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

return next.handle(request).pipe(
  retry(1),
  catchError((error: HttpErrorResponse) => {
    let errorMsg;
    if (error.error instanceof Error) {
        // A client-side or network error occurred. Handle it accordingly.
        errorMsg = 'An error occurred: ${error.error.message}';
    } else {
        // The backend returned an unsuccessful response code.
        // The response body may contain clues as to what went wrong,
        errorMsg = 'Backend returned code ${error.status}, body was: ${error.error}';
    }
    if (error.status === 401 || error.status === 403) {

        this.injector.get(NotificationService).showUnathorized(errorMsg);
        this.injector.get(Router).navigateByUrl('/auth/login');
    } else {
      return throwError(error);
    }
  })
);

} }`

insert short code snippets here

Other information:

npm, node, OS, Browser

<!--
Node, npm: `node --version` and `npm --version`
OS: Windows (7/8/10). Linux (incl. distribution). macOS (El Capitan? Sierra?)
Browser: Chrome/Safari/Firefox/etc?
-->

Angular, Nebular

<!--
Check your `package-lock.json` or locate a `package.json` in the `node_modules` folder.
-->
`{
  "name": "crm-app",
  "version": "4.0.1",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/akveo/ngx-admin.git"
  },
  "bugs": {
    "url": "https://github.com/akveo/ngx-admin/issues"
  },
  "scripts": {
    "ng": "ng",
    "conventional-changelog": "conventional-changelog",
    "start": "ng serve --host 0.0.0.0",
    "build": "ng build",
    "build:prod": "npm run build -- --prod --aot",
    "test": "ng test",
    "test:coverage": "rimraf coverage && npm run test -- --code-coverage",
    "lint": "ng lint",
    "lint:fix": "ng lint crm-app --fix",
    "lint:styles": "stylelint ./src/**/*.scss",
    "lint:ci": "npm run lint && npm run lint:styles",
    "pree2e": "webdriver-manager update --standalone false --gecko false",
    "e2e": "ng e2e",
    "docs": "compodoc -p src/tsconfig.app.json -d docs",
    "docs:serve": "compodoc -p src/tsconfig.app.json -d docs -s",
    "prepush": "npm run lint:ci",
    "release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s",
    "postinstall": "ngcc --properties es2015 es5 browser module main --first-only --create-ivy-entry-points"
  },
  "dependencies": {
    "@akveo/ng2-completer": "^9.0.1",
    "@angular/animations": "^9.0.4",
    "@angular/cdk": "^9.1.2",
    "@angular/common": "^9.0.4",
    "@angular/compiler": "^9.0.4",
    "@angular/core": "^9.0.4",
    "@angular/forms": "^9.0.4",
    "@angular/material": "^9.1.0",
    "@angular/platform-browser": "^9.0.4",
    "@angular/platform-browser-dynamic": "^9.0.4",
    "@angular/router": "^9.0.4",
    "@asymmetrik/ngx-leaflet": "3.0.1",
    "@nebular/auth": "5.0.0",
    "@nebular/eva-icons": "5.0.0",
    "@nebular/security": "^5.0.0",
    "@nebular/theme": "5.0.0",
    "@swimlane/ngx-charts": "^13.0.2",
    "angular2-chartjs": "0.4.1",
    "bootstrap": "4.3.1",
    "chart.js": "^2.7.1",
    "ckeditor": "4.7.3",
    "classlist.js": "1.1.20150312",
    "core-js": "2.5.1",
    "echarts": "^4.0.2",
    "eva-icons": "^1.1.3",
    "intl": "1.2.5",
    "ionicons": "2.0.1",
    "leaflet": "1.2.0",
    "nebular-icons": "1.1.0",
    "ng2-charts": "^2.3.2",
    "ng2-ckeditor": "^1.2.2",
    "ng2-smart-table": "^1.6.0",
    "ngx-echarts": "^4.2.2",
    "node-sass": "^4.12.0",
    "normalize.css": "6.0.0",
    "pace-js": "1.0.2",
    "roboto-fontface": "0.8.0",
    "rxjs": "6.5.4",
    "rxjs-compat": "6.3.0",
    "socicon": "3.0.5",
    "style-loader": "^1.1.3",
    "tinymce": "4.5.7",
    "tslib": "^1.10.0",
    "typeface-exo": "0.0.22",
    "web-animations-js": "^2.3.2",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.900.4",
    "@angular/cli": "^9.0.4",
    "@angular/compiler-cli": "^9.0.4",
    "@angular/language-service": "9.0.4",
    "@compodoc/compodoc": "1.0.1",
    "@fortawesome/fontawesome-free": "^5.2.0",
    "@types/d3-color": "1.0.5",
    "@types/jasmine": "2.5.54",
    "@types/jasminewd2": "2.0.3",
    "@types/leaflet": "1.2.3",
    "@types/node": "^12.11.1",
    "codelyzer": "^5.1.2",
    "conventional-changelog-cli": "1.3.4",
    "jasmine-core": "2.6.4",
    "jasmine-spec-reporter": "4.1.1",
    "karma": "1.7.1",
    "karma-chrome-launcher": "2.1.1",
    "karma-cli": "1.0.1",
    "karma-coverage-istanbul-reporter": "1.3.0",
    "karma-jasmine": "1.1.0",
    "karma-jasmine-html-reporter": "0.2.2",
    "npm-run-all": "4.0.2",
    "protractor": "5.1.2",
    "rimraf": "2.6.1",
    "stylelint": "7.13.0",
    "ts-node": "3.2.2",
    "tslint": "^5.7.0",
    "tslint-language-service": "^0.9.9",
    "typescript": "3.7.5",
    "yargs": "^15.4.0"
  }
}
`

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:4
  • Comments:12

github_iconTop GitHub Comments

2reactions
luuisAfonsocommented, Aug 4, 2021

I found a possible solution, apparently if you takes too long the log again on the login strategy that you are using, and tries to login without already been properly logged out the nebular will somehow get in a infinite loop, for exemple, when the token still present in the browser local storage if you are using the localStorageStrategy for token storage and tries to login.

that’s explain why the login works in other browsers (that you haven’t logged before) and also works in incognito mode.

The solution cab be achieved by extending the NbLoginComponent, then getting access to the NbTokenStorage by dependency injection and clearing the token before the login happens

e.g:

@Component({
  selector: 'ngx-login',
  templateUrl: './login.component.html',
})
export class NgxLoginComponent extends NbLoginComponent {

  constructor(
      service: NbAuthService,
      @Inject(NB_AUTH_OPTIONS) protected options: {},
      cd: ChangeDetectorRef, router: Router,
      private tokenStorageService: NbTokenStorage
    ) {
    super(service, options, cd, router);
  }

  login(): void {
    this.tokenStorageService.clear(); // this clear the token from the storage accordingly with the storage strategy
    super.login();
  }

}
2reactions
Ashwin-opcommented, May 5, 2021

A temporary solution is to clear the site data in Developer Tools > Application

Read more comments on GitHub >

github_iconTop Results From Across the Web

Maximum call stack size exceeded - Google Maps Api
I have an app that displays an array of markers on google maps. It was working just fine until recently I noticed this...
Read more >
JavaScript RangeError: Maximum Call Stack Size Exceeded
The RangeError: Maximum call stack size exceeded is thrown when a function call is made that exceeds the call stack size. This can...
Read more >
JavaScript Error: Maximum Call Stack Size Exceeded
If you see the “Maximum Call Stack Size Exceeded” error, there's likely a problem with a recursive function within your JavaScript code.
Read more >
Maximum call stack size exceeded - Netlify Support Forums
PLEASE help us help you by writing a good post! we need to know your netlify site name. Example: gifted-antelope-58b104.netlify.app DNS ...
Read more >
Avoid Maximum call stack size exceeded in JavaScript
Overview · Error Maximum call stack size exceeded is raised when calling a recursive function in a loop · This is expected –...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found