Angular Universal - TypeError: Converting circular structure to JSON

549 Views Asked by At

I am having a big problem related to Angular Server-Side Rendering (SSR), the usage of Resolvers and HTTP requests. I am building a project in Angular 13, but I decided to implement SSR in order to improve the experience with SEO and redirection in case of a change in the structure of the URL.

I decided to install it through ng add @nguniversal/express-engine as reported in the documentation. Unfortunately, when I start the application with ng run project:serve-ssr all builds correctly, but when I visit the homepage which uses Resolvers with services generated with ng-openapi-gen, the page does not render and I receive the following error.

ERROR TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'XMLHttpRequest'
    |     property 'upload' -> object with constructor 'XMLHttpRequestUpload'
    --- property '_request' closes the circle
    at JSON.stringify (<anonymous>)
    at readableObjectToString (/home/user/project/dist/project/server/main.js:122623:59)
    at resolvePromise (/home/user/project/dist/project/server/main.js:122823:59)
    at resolvePromise (/home/user/project/dist/project/server/main.js:122770:11)
    at /home/user/project/dist/project/server/main.js:122897:11
    at _ZoneDelegate.invokeTask (/home/user/project/dist/project/server/main.js:121862:173)
    at Object.onInvokeTask (/home/user/project/dist/project/server/main.js:205242:33)
    at _ZoneDelegate.invokeTask (/home/user/project/dist/project/server/main.js:121862:56)
    at Zone.runTask (/home/user/project/dist/project/server/main.js:121612:39)
    at drainMicroTaskQueue (/home/user/project/dist/project/server/main.js:122082:25) {
  rejection: HttpErrorResponse {
    headers: HttpHeaders {
      normalizedNames: Map {},
      lazyUpdate: null,
      headers: Map {}
    },
    status: 0,
    statusText: 'Unknown Error',
    url: 'https://localhost:4200/api/v1/chords/',
    ok: false,
    name: 'HttpErrorResponse',
    message: 'Http failure response for https://localhost:4200/api/v1/chords/: 0 Unknown Error',
    error: ProgressEvent {
      type: 'error',
      target: [XMLHttpRequest],
      currentTarget: [XMLHttpRequest],
      lengthComputable: false,
      loaded: 0,
      total: 0
    }
  },
  promise: ZoneAwarePromise [Promise] {
    __zone_symbol__state: 0,
    __zone_symbol__value: HttpErrorResponse {
      headers: [HttpHeaders],
      status: 0,
      statusText: 'Unknown Error',
      url: 'https://localhost:4200/api/v1/chords/',
      ok: false,
      name: 'HttpErrorResponse',
      message: 'Http failure response for https://localhost:4200/api/v1/chords/: 0 Unknown Error',
      error: [ProgressEvent]
    }
  },
  zone: Zone {
    _parent: Zone {
      _parent: null,
      _name: '<root>',
      _properties: {},
      _zoneDelegate: [_ZoneDelegate]
    },
    _name: 'angular',
    _properties: { isAngularZone: true },
    _zoneDelegate: _ZoneDelegate {
      _taskCounts: [Object],
      zone: [Circular],
      _parentDelegate: [_ZoneDelegate],
      _forkZS: null,
      _forkDlgt: null,
      _forkCurrZone: null,
      _interceptZS: null,
      _interceptDlgt: null,
      _interceptCurrZone: null,
      _invokeZS: [Object],
      _invokeDlgt: [_ZoneDelegate],
      _invokeCurrZone: [Circular],
      _handleErrorZS: [Object],
      _handleErrorDlgt: [_ZoneDelegate],
      _handleErrorCurrZone: [Circular],
      _scheduleTaskZS: [Object],
      _scheduleTaskDlgt: [_ZoneDelegate],
      _scheduleTaskCurrZone: [Circular],
      _invokeTaskZS: [Object],
      _invokeTaskDlgt: [_ZoneDelegate],
      _invokeTaskCurrZone: [Circular],
      _cancelTaskZS: [Object],
      _cancelTaskDlgt: [_ZoneDelegate],
      _cancelTaskCurrZone: [Circular],
      _hasTaskZS: [Object],
      _hasTaskDlgt: [_ZoneDelegate],
      _hasTaskDlgtOwner: [Circular],
      _hasTaskCurrZone: [Circular]
    }
  },
  task: ZoneTask {
    _zone: Zone {
      _parent: [Zone],
      _name: 'angular',
      _properties: [Object],
      _zoneDelegate: [_ZoneDelegate]
    },
    runCount: 0,
    _zoneDelegates: null,
    _state: 'notScheduled',
    type: 'microTask',
    source: 'Promise.then',
    data: ZoneAwarePromise [Promise] {
      __zone_symbol__state: 0,
      __zone_symbol__value: [HttpErrorResponse]
    },
    scheduleFn: undefined,
    cancelFn: undefined,
    callback: [Function],
    invoke: [Function]
  }
}

I noticed that if I remove the reference to the resolvers in the routing, the page renders correctly (with obvious errors related to the rendering of objects that are resolver-dependent), so I am figuring out that the problem is in the resolvers.

Did you already have this problem and/or do you know how to fix this problem? Thanks in advance.

1

There are 1 best solutions below

0
On

I recently faced the exact same error and was able to identify the issue.

The error occurs when your Angular SSR app cannot reach your API endpoints while performing the server-side rendering part. Unfortunately, the error message is completely misleading.

There can be different reasons why your server can't reach your endpoint, for example a firewall could be blocking the requests.

If you use docker, make sure your containers can communicate with each other and use the right endpoint URL. In my case, using 'localhost' when calling the API caused this issue and I had to perform the server-side requests through the internal docker network.