{"record":{"id":"dcf99e1f7a0f07a0","repo":"angular/components","slug":"provided-data-source-did-not-match-an-array-obser","errorCode":null,"errorMessage":"Provided data source did not match an array, Observable, or DataSource","messagePattern":"Provided data source did not match an array, Observable, or DataSource","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cdk/table/table.ts","lineNumber":1245,"sourceCode":"  /** Set up a subscription for the data provided by the data source. */\n  private _observeRenderChanges() {\n    // If no data source has been set, there is nothing to observe for changes.\n    if (!this.dataSource) {\n      return;\n    }\n\n    let dataStream: Observable<readonly T[]> | undefined;\n\n    if (isDataSource(this.dataSource)) {\n      dataStream = this.dataSource.connect(this);\n    } else if (isObservable(this.dataSource)) {\n      dataStream = this.dataSource;\n    } else if (Array.isArray(this.dataSource)) {\n      dataStream = observableOf(this.dataSource);\n    }\n\n    if (dataStream === undefined && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n      throw getTableUnknownDataSourceError();\n    }\n\n    this._renderChangeSubscription = combineLatest([dataStream!, this.viewChange])\n      .pipe(takeUntil(this._onDestroy))\n      .subscribe(([data, range]) => {\n        this._data = data || [];\n        this._renderedRange = range;\n        this._dataStream.next(data);\n        this.renderRows();\n      });\n  }\n\n  /**\n   * Clears any existing content in the header row outlet and creates a new embedded view\n   * in the outlet using the header row definition.\n   */\n  private _forceRenderHeaderRows() {\n    // Clear the header row outlet if any content exists.","sourceCodeStart":1227,"sourceCodeEnd":1263,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/table/table.ts#L1227-L1263","documentation":"The table's dataSource input was set to something that is neither an array, an Observable, nor an object implementing DataSource, so no data stream could be derived. In dev mode the table throws rather than rendering an empty table.","triggerScenarios":"In _observeRenderedContent / renderChanges: dataSource is truthy but not Array.isArray(dataSource), not a DataSource, and not a subscribed Observable, leaving dataStream === undefined.","commonSituations":"Passing a Promise directly (not supported); passing an incorrectly instantiated DataSource (e.g. missing connect()); binding the wrong variable such as dataSource=\"data\" (string) instead of [dataSource]=\"data\"; passing undefined via a wrong property path that isn't caught because of a truthy non-stream object.","solutions":["Pass a plain array: [dataSource]=\"myArray\"","Or pass an Observable: [dataSource]=\"data$\"","Or implement/extend MatTableDataSource (or DataSource<T>) and pass an instance","Check the binding uses property binding [dataSource] not the literal attribute dataSource","Convert a Promise with from(promise) or toDataSource-style wrapping"],"exampleFix":"// before\n<table mat-table dataSource=\"users\">\n// after\n<table mat-table [dataSource]=\"users\">  <!-- users: User[] | Observable<User[]> | MatTableDataSource<User> -->","handlingStrategy":"type-guard","validationCode":"function isValidDataSource(src: unknown): boolean {\n  return Array.isArray(src) || src instanceof Observable ||\n    (typeof src === 'object' && src !== null && 'connect' in src);\n}\nif (!isValidDataSource(this.dataSource)) throw new TypeError('dataSource must be array, Observable, or DataSource');","typeGuard":"function isDataSource<T>(src: unknown): src is DataSource<T> {\n  return typeof src === 'object' && src !== null && typeof (src as any).connect === 'function';\n}","tryCatchPattern":"try {\n  this.cdr.detectChanges();\n} catch (e) {\n  if (/did not match an array, Observable, or DataSource/.test(e.message)) {\n    console.error('Use [dataSource] with an array, Observable, or MatTableDataSource instance');\n  }\n}","preventionTips":["Always use property binding [dataSource]=\"...\"","Convert Promises with from(promise) before assigning","Use MatTableDataSource for filtering/sorting/paging features"],"tags":["angular","cdk-table","datasource","type-mismatch"],"backgroundTag":"invalid-datasource-type","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}