{"record":{"id":"48d5f0b05bbfa539","repo":"angular/components","slug":"default-implementation-of-filterpredicate-requires","errorCode":null,"errorMessage":"Default implementation of filterPredicate requires data to be a non-null object.","messagePattern":"Default implementation of filterPredicate requires data to be a non-null object\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/material/table/table-data-source.ts","lineNumber":240,"sourceCode":"    });\n  };\n\n  /**\n   * Checks if a data object matches the data source's filter string. By default, each data object\n   * is converted to a string of its properties and returns true if the filter has\n   * at least one occurrence in that string. By default, the filter string has its whitespace\n   * trimmed and the match is case-insensitive. May be overridden for a custom implementation of\n   * filter matching.\n   * @param data Data object used to check against the filter.\n   * @param filter Filter string that has been set on the data source.\n   * @returns Whether the filter matches against the data\n   */\n  filterPredicate: (data: T, filter: string) => boolean = (data: T, filter: string): boolean => {\n    if (\n      (typeof ngDevMode === 'undefined' || ngDevMode) &&\n      (typeof data !== 'object' || data === null)\n    ) {\n      console.warn(\n        'Default implementation of filterPredicate requires data to be a non-null object.',\n      );\n    }\n\n    // Transform the filter by converting it to lowercase and removing whitespace.\n    const transformedFilter = filter.trim().toLowerCase();\n    // Loops over the values in the array and returns true if any of them match the filter string\n    // TODO: Remove `as object` cast when `T` stops extending `any`:\n    return Object.values(data as object).some(value =>\n      `${value}`.toLowerCase().includes(transformedFilter),\n    );\n  };\n\n  constructor(initialData: T[] = []) {\n    super();\n    this._data = new BehaviorSubject<T[]>(initialData);\n    this._updateChangeSubscription();\n  }","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/material/table/table-data-source.ts#L222-L258","documentation":"MatTableDataSource's default filterPredicate expects each row (data) to be a non-null object because it iterates object values with Object.values and stringifies them for matching. In dev mode it warns via console.warn when a row is not an object (e.g. a primitive, null, or undefined). The warning does not stop filtering, but the default predicate cannot match against such rows correctly.","triggerScenarios":"Assigning MatTableDataSource a data array whose elements are primitives (string/number) or containing null/undefined rows, then setting the `filter` property so the default filterPredicate runs on each row.","commonSituations":"Binding a table directly to an array of strings or numbers (e.g. a list of names); API returning arrays of scalars; null entries from unfiltered API responses; developers expecting default filtering to work on primitive rows.","solutions":["Wrap primitives in objects: data = values.map(v => ({value: v})) and bind that to the data source.","Provide a custom filterPredicate that handles your row type: dataSource.filterPredicate = (data, filter) => data.toString().includes(filter).","Sanitize the data array before assignment (filter out null/undefined rows)."],"exampleFix":"// before\ndatasource.data = ['apple', 'banana'];\n// after\ndatasource.data = ['apple', 'banana'].map(name => ({name}));\n// or\ndatasource.filterPredicate = (data: string, filter: string) => data.includes(filter);","handlingStrategy":"type-guard","validationCode":"if (!rows.every(r => r !== null && typeof r === 'object')) {\n  throw new Error('MatTableDataSource rows must be non-null objects');\n}","typeGuard":"function isFilterableRow<T>(row: T | null | undefined): row is T & object {\n  return row !== null && row !== undefined && typeof row === 'object';\n}","tryCatchPattern":null,"preventionTips":["Always model table rows as objects ({value: x}) instead of raw primitives.","Sanitize API data: rows.filter(r => r != null) before assigning to dataSource.data.","Override filterPredicate whenever your row type is unusual."],"tags":["angular","material-table","filtering","data-source"],"backgroundTag":"invalid-data-shape-for-filter","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}