Abp: Angular ApiInterceptor - Default/host tenantId 'cannot read property length of null error' - since 4.0.x

Created on 15 Dec 2020  路  3Comments  路  Source: abpframework/abp

  • Your ABP Framework version - 4.0.x (tested 4.0.0 and 4.0.1)
  • Your User Interface - Angular
  • Exception message and stack trace if available (check the logs).

ApiInterceptor incorrectly has a null error (it tries to determine append the multi-tenancy HTTP header, but the tenantId is null by default).
Might be related to work done new storage solution in Angular: https://github.com/abpframework/abp/issues/5606

angular-oauth2-oidc.js:1330 error loading discovery document TypeError: Cannot read property 'length' of null
    at HttpHeaders.applyUpdate (http.js:235)
    at http.js:207
    at Array.forEach (<anonymous>)
    at HttpHeaders.init (http.js:207)
    at HttpHeaders.forEach (http.js:270)
    at Observable._subscribe (http.js:1589)
    at Observable._trySubscribe (Observable.js:42)
    at Observable.subscribe (Observable.js:28)
    at FinallyOperator.call (finalize.js:11)
    at Observable.subscribe (Observable.js:23)
(anonymous) @ angular-oauth2-oidc.js:1330
...
core.js:6006 ERROR TypeError: Cannot read property 'length' of null
    at HttpHeaders.applyUpdate (http.js:235)
    at http.js:207
    at Array.forEach (<anonymous>)
    at HttpHeaders.init (http.js:207)
    at HttpHeaders.forEach (http.js:270)
    at Observable._subscribe (http.js:1589)
    at Observable._trySubscribe (Observable.js:42)
    at Observable.subscribe (Observable.js:28)
    at FinallyOperator.call (finalize.js:11)
    at Observable.subscribe (Observable.js:23)
defaultErrorLogger @ core.js:6006
...
main.ts:13 TypeError: Cannot read property 'length' of null
    at HttpHeaders.applyUpdate (http.js:235)
    at http.js:207
    at Array.forEach (<anonymous>)
    at HttpHeaders.init (http.js:207)
    at HttpHeaders.forEach (http.js:270)
    at Observable._subscribe (http.js:1589)
    at Observable._trySubscribe (Observable.js:42)
    at Observable.subscribe (Observable.js:28)
    at FinallyOperator.call (finalize.js:11)
    at Observable.subscribe (Observable.js:23)`
localStorage:
{"abpSession": {"language":"en","tenant":{"id":null,"name":null,"isAvailable":false}}
  • Steps needed to reproduce the problem.
    Start default Angular template with @apb/ng.core package v4.0.0 or v4.0.1 to include the CoreModule.
    Load Angular page two times: the first time the default "abpSession" is written to localStorage. The second time the tenantId is incorrectly interpreted (null exception) as a string with length property (ApiInterceptor).

I also did this without the template (setup from a new Angular project). Same thing and that makes sense.

Proposed solution

if (!(existingHeaders === null || existingHeaders === void 0 ? void 0 : existingHeaders.has('__tenant')) && tenant) {
    headers['__tenant'] = tenant.id;
}

return headers;       

changed to

if (!(existingHeaders === null || existingHeaders === void 0 ? void 0 : existingHeaders.has('__tenant')) && tenant?.id) {
    headers['__tenant'] = tenant.id;
}

return headers;       

Most helpful comment

3 solutions:

  • install 4.1.0-rc.1 (the problem is fixed)
  • revert to 4.0.0
  • delete the abpSession tenant key by hand. Below is a failing attempt to do so. Not advised.

Attempt to fix - still fails often:

Add this to main.ts before the app runs (or use an APP_INITIALIZATION factory/class at your own risk of a race condition with the app loading with ApiInterceptor)

import {Session} from '@abp/ng.core';

let abpSession = JSON.parse(localStorage.getItem("abpSession")) as Session.State;
if (abpSession && abpSession.tenant?.id == null) {
    delete abpSession.tenant;
    localStorage.setItem("abpSession", JSON.stringify(abpSession));
}

All 3 comments

3 solutions:

  • install 4.1.0-rc.1 (the problem is fixed)
  • revert to 4.0.0
  • delete the abpSession tenant key by hand. Below is a failing attempt to do so. Not advised.

Attempt to fix - still fails often:

Add this to main.ts before the app runs (or use an APP_INITIALIZATION factory/class at your own risk of a race condition with the app loading with ApiInterceptor)

import {Session} from '@abp/ng.core';

let abpSession = JSON.parse(localStorage.getItem("abpSession")) as Session.State;
if (abpSession && abpSession.tenant?.id == null) {
    delete abpSession.tenant;
    localStorage.setItem("abpSession", JSON.stringify(abpSession));
}

We have fixed this problem: https://github.com/abpframework/abp/pull/6644

Ah sorry for the dupe, still the script above could help some. Thx!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wakuflair picture wakuflair  路  3Comments

Trojaner picture Trojaner  路  3Comments

vfabregat picture vfabregat  路  3Comments

hikalkan picture hikalkan  路  3Comments

hikalkan picture hikalkan  路  3Comments