ReactiveX / ReactiveX/rxjs

You provided an invalid object where a stream was expected error in Module Federation environment

Open
#6,628 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
31.7k
Forks
3k
PR merge metrics
No merged PRs in 30d

Description

Bug Report

Current Behavior

switchMap (and other mapping operators) might not work correctly in Module Federation environment.

Code like:

this
  .getSomeObservable()
  .pipe(
    switchMap(() => this.getOtherObservable()) // switching here causes the error
  ).subscribe()

Will cause : You provided an invalid object where a stream was expected error in Module Federation environment exception

Expected behavior

Mapping operators should work and recognise

Reproduction

I was not able yet to reproduce it with a repo I could publicly push. This is explanation from the app I'm maintaining.

I've migrated one app to MFE Architecture using Module Federation and mysteriously looking error is thrown at runtime:

You provided an invalid object where a stream was expected error. You can provide an Observable, Promise, Array, or Iterable.

The code that causes it looks like this:

this
  .getSomeObservable()
  .pipe(
    switchMap(() => this.getOtherObservable()) // switching here causes the error
  ).subscribe()

However I was pretty sure code was ok...

When analysing stack trace, error originates from:

https://github.com/ReactiveX/rxjs/blob/6.6.7/src/internal/util/subscribeTo.ts

export const subscribeTo = <T>(result: ObservableInput<T>): (subscriber: Subscriber<T>) => Subscription | void => {
  if (!!result && typeof result[Symbol_observable] === 'function') {
    return subscribeToObservable(result as any);
  } else if (isArrayLike(result)) {
    return subscribeToArray(result);
  } else if (isPromise(result)) {
    return subscribeToPromise(result as Promise<any>);
  } else if (!!result && typeof result[Symbol_iterator] === 'function') {
    return subscribeToIterable(result as any);
  } else {
    const value = isObject(result) ? 'an invalid object' : `'${result}'`;
    const msg = `You provided ${value} where a stream was expected.`
      + ' You can provide an Observable, Promise, Array, or Iterable.';
    throw new TypeError(msg);
  }
};

In my case, result is of type BehaviorSubject.

However, when I compared stack trace when app is running in non-federated to federated, the issue is here:

https://github.com/ReactiveX/rxjs/blob/6.6.7/src/internal/innerSubscribe.ts#L110

  if (result instanceof Observable) {
    return result.subscribe(innerSubscriber);
  }

Without module federation, this if is truthy, when I look at prototypes, deeper I can find Observable.

However in federated environment, this expression is falsy.

The good news it that refactoring to:

this
  .getSomeObservable()
  .subscribe(() => this.getOtherObservable().subscribe())

does not throw error any more.

Environment

  • RxJS version: 6.6.7
  • Build configuration: webpack@5.50.0

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/internal/util/subscribeTo.ts and src/internal/innerSubscribe.ts, then investigate the reported BehaviorSubject case under RxJS 6.6.7 with webpack 5.50 Module Federation. Reproduce the federated and non-federated behavior if possible; done means switchMap and other mapping operators accept the returned observable without the invalid-object error.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript, webpack
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.