Taylor Ackley
Taylor Ackley

Reputation: 1437

Angular 8: ERROR Error: Uncaught (in promise): TypeError: You provided an invalid object where a stream was expected

I have a recently upgraded Angular app (Angular v7 => v8) and everything used to work just fine.

But now, after switching to 8, I get an error in my login function (below). The error is most likely easy to resolve, but the stack trace makes little sense. It doesn't show where the type error actually happens, except for in the vendor code.

I tried to take a few stabs in the dark at fixing it, such as resolving the promise returned from this.router.navigate, turning the subscribe into a promise, adding a console.log to the auth guard to see if it stops there (it doesn't) and finally, I added some logging code to my screen (screen after login), and nothing was getting logged.

Has anyone run into this? I reviewed the upgrade notes and didn't see anything stick out. If anybody has any tips to figure out where this is happening, I can take it from there.

Login Code:

    this.clearAlerts();
    localStorage.setItem('persistLogin', this.persistLogin.toString());
    this.svc
      .login(this.user).subscribe((res: ApiResponse) => {
        console.log(res);
        this.router.navigate([res.action.href]);
      }, err => {
          console.log(err);
        this.error = err.error.message;
        if (err.error.action) {
          this.links.resolve(err.error);
        }
      }, () => console.log('done'));
  }

Error Message:

Happens after done.

    core.js:6014 ERROR Error: Uncaught (in promise): TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
    TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
        at subscribeTo (subscribeTo.js:27)
        at from (from.js:9)
        at Observable._subscribe (defer.js:14)
        at Observable._trySubscribe (Observable.js:42)
        at Observable.subscribe (Observable.js:28)
        at TakeOperator.call (take.js:22)
        at Observable.subscribe (Observable.js:23)
        at subscribeToResult (subscribeToResult.js:9)
        at MergeMapSubscriber._innerSub (mergeMap.js:59)
        at MergeMapSubscriber._tryNext (mergeMap.js:53)
        at resolvePromise (zone-evergreen.js:793)
        at resolvePromise (zone-evergreen.js:752)
        at zone-evergreen.js:854
        at ZoneDelegate.invokeTask (zone-evergreen.js:400)
        at Object.onInvokeTask (core.js:39680)
        at ZoneDelegate.invokeTask (zone-evergreen.js:399)
        at Zone.runTask (zone-evergreen.js:168)
        at drainMicroTaskQueue (zone-evergreen.js:570)
        at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:485)
        at invokeTask (zone-evergreen.js:1596)

EDIT - Login Svc Code added.

Login Svc Code - Note, I tried removing this and got the same error

login(user: User) {
    return this.http.post(`${environment.api}/account/login`, user).pipe(
      map((res: ApiResponse) => {
        localStorage.setItem('token', res.payload);
        return res;
      }),
      map(
        (res: ApiResponse) => {
          const timer$ = timer(0, REFRESH_INTERVAL);
          this.$isAuthenticated = timer$.pipe(
            switchMap(_ => this.getIsAuthenticated()),
            shareReplay(CACHE_SIZE)
          );
          return res;
        },
        map((res: ApiResponse) => {
          const timer$ = timer(0, REFRESH_INTERVAL);
          this.$user = timer$.pipe(
            switchMap(_ => this.getSelf()),
            shareReplay(CACHE_SIZE)
          );
          return res;
        })
    )
    );
  }

EDIT 2 Add Home Component

Home Component Code (M

import { Component, OnInit } from '@angular/core';
import { select, Store } from '@ngrx/store';
import { Subscription } from 'rxjs';
import { User } from '../../models/user.model';
import { AppService } from '../../services/app.service';
import { IState } from '../../store/reducers';
import { selectApp } from '../../store/selectors/app.selectors';
import { IAppState } from './../../store/state/app.state';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
  homeContent = [];
  user: User;
  contentSub: Subscription;
  sub: Subscription;
  appState$ = this._store.pipe(select(selectApp));
  state: IAppState;
  constructor(private svc: AppService, private _store: Store<IState>) {}

  ngOnInit() {
    console.log('123');
    this.contentSub = this.svc
      .getHomeContent()
      .subscribe(res => {
        console.log(123451232);
        this.homeContent = res.payload.items;
      });
    this.appState$.subscribe(value => {
      console.log(12345);
      this.user = value.user;
    });
  }
}

Selector Code:

import { createSelector } from '@ngrx/store';
import { IState } from '../reducers';
import { IAppState } from '../state/app.state';

const appState = (state: IState) => state.app;

export const selectApp = createSelector(
  appState,
  (state: IAppState) => state.app
);

Environment:

Angular CLI: 8.3.20
Node: 10.18.0
OS: win32 x64
Angular: 8.2.14

Upvotes: 2

Views: 9312

Answers (1)

Taylor Ackley
Taylor Ackley

Reputation: 1437

I finally solved this when I found out I had a circular dependency.

I ran ng build --aot which threw a warning about a circular dependency in my app.module.ts file.

At the bottom of the file, I noticed I had:

platformBrowserDynamic().bootstrapModule(AppModule);. In essence referencing itself. I did some quick googling and found out that line belongs in main.ts.

Moved the line and the problem went away.

Upvotes: 1

Related Questions