{"record":{"id":"779b21f6f1bee8da","repo":"angular/components","slug":"unknown-data-source","errorCode":null,"errorMessage":"Unknown data source","messagePattern":"Unknown data source","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cdk-experimental/selection/selection.ts","lineNumber":107,"sourceCode":"  }\n\n  private _observeRenderChanges() {\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 (this._dataSource instanceof Observable) {\n      dataStream = this._dataSource;\n    } else if (Array.isArray(this._dataSource)) {\n      dataStream = observableOf(this._dataSource);\n    }\n\n    if (dataStream == null && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n      throw Error('Unknown data source');\n    }\n\n    this._renderChangeSubscription = dataStream!\n      .pipe(takeUntil(this._destroyed))\n      .subscribe(data => {\n        this._data = data || [];\n      });\n  }\n\n  ngOnInit() {\n    this._selection = new SelectionSet<T>(this._multiple, this.trackByFn);\n    this._selection.changed.pipe(takeUntil(this._destroyed)).subscribe(change => {\n      this._updateSelectAllState();\n      this.change.emit(change);\n    });\n  }\n\n  ngAfterContentChecked() {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk-experimental/selection/selection.ts#L89-L125","documentation":"CdkSelection._observeRenderChanges resolves its data source as a stream: a Connect/Observable input, or an array wrapped with observableOf. If _dataSource is neither (null, undefined, or an unsupported type like a plain object), the dev-mode check throws 'Unknown data source' before subscribing, because there is no way to obtain the data stream.","triggerScenarios":"Binding [dataSource] to null/undefined (e.g., async data that has not resolved yet); passing a plain non-array object; assigning an incompatible type after a refactor; forgetting the dataSource input entirely.","commonSituations":"Data loaded asynchronously so the property is undefined on first render before ngAfterContentChecked; migrating from MatTableDataSource which CdkSelection does not understand; server responses typed as object instead of array.","solutions":["Pass an array: [dataSource]=\"items\" — it will be wrapped in of(items) automatically.","Or pass a stream (Observable/Connect) that emits arrays, holding a default of [] until data arrives: items$ = http$.pipe(startWith([])).","Initialize the bound property to [] rather than undefined while loading."],"exampleFix":"// before\n@Input() dataSource; // undefined until fetch resolves\n\n// after\nitems: T[] = [];\nthis.api.load().subscribe(d => this.items = d);\n<cdk-selection [dataSource]=\"items\">","handlingStrategy":"validation","validationCode":"function isValidDataSource(src: unknown): src is readonly unknown[] | Observable<unknown[]> {\n  return Array.isArray(src) || (src instanceof Observable);\n}\nif (!isValidDataSource(this.dataSource)) throw new Error('CdkSelection dataSource must be an array or Observable');","typeGuard":"function isSelectableDataSource<T>(src: unknown): src is T[] | Observable<T[]> {\n  return Array.isArray(src) || src instanceof Observable;\n}","tryCatchPattern":"try {\n  selection.dataSource = maybeSource;\n  cdr.detectChanges();\n} catch (e) {\n  if ((e as Error).message === 'Unknown data source') {\n    selection.dataSource = [];\n  } else throw e;\n}","preventionTips":["Initialize dataSource-bound properties to [] instead of null/undefined.","Only pass arrays or Observables — never MatTableDataSource or plain objects.","Use startWith([]) on async streams so a value exists before first check."],"tags":["angular","cdk","selection","data-source","dev-mode-assertion"],"backgroundTag":"invalid-data-source-type","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}