{"record":{"id":"1f7dc48185f7b784","repo":"angular/components","slug":"trackby-must-be-a-function-but-received-json-st","errorCode":null,"errorMessage":"trackBy must be a function, but received ${JSON.stringify(fn)}.","messagePattern":"trackBy must be a function, but received (.+?)\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/cdk/table/table.ts","lineNumber":500,"sourceCode":"    }\n\n    return this._cellRoleInternal;\n  }\n  private _cellRoleInternal: string | null | undefined = undefined;\n\n  /**\n   * Tracking function that will be used to check the differences in data changes. Used similarly\n   * to `ngFor` `trackBy` function. Optimize row operations by identifying a row based on its data\n   * relative to the function to know if a row should be added/removed/moved.\n   * Accepts a function that takes two parameters, `index` and `item`.\n   */\n  @Input()\n  get trackBy(): TrackByFunction<T> {\n    return this._trackByFn;\n  }\n  set trackBy(fn: TrackByFunction<T>) {\n    if ((typeof ngDevMode === 'undefined' || ngDevMode) && fn != null && typeof fn !== 'function') {\n      console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}.`);\n    }\n    this._trackByFn = fn;\n  }\n  private _trackByFn!: TrackByFunction<T>;\n\n  /**\n   * The table's source of data, which can be provided in three ways (in order of complexity):\n   *   - Simple data array (each object represents one table row)\n   *   - Stream that emits a data array each time the array changes\n   *   - `DataSource` object that implements the connect/disconnect interface.\n   *\n   * If a data array is provided, the table must be notified when the array's objects are\n   * added, removed, or moved. This can be done by calling the `renderRows()` function which will\n   * render the diff since the last table render. If the data array reference is changed, the table\n   * will automatically trigger an update to the rows.\n   *\n   * When providing an Observable stream, the table will trigger an update automatically when the\n   * stream emits a new array of data.","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/table/table.ts#L482-L518","documentation":"The CDK data-table's `trackBy` input must be a `TrackByFunction<T>`. In dev mode, assigning a non-function truthy value logs this warning (the value is stored anyway, and Angular will then break at runtime when it tries to call it). The library warns instead of throwing so that production builds with `ngDevMode` stripped are unaffected.","triggerScenarios":"Binding something other than a function to `trackBy`, e.g. `trackBy=\"myTrackById\"` in a template (string, not function reference), `trackBy={id: ...}` object, or calling it: `trackBy=\"trackById()\"`.","commonSituations":"Copy-pasting `trackBy` usage from `*ngFor` examples where a string worked differently, forgetting the `this.`/method reference, or binding an observable-mapped value that isn't a function.","solutions":["Bind an actual function reference: `trackBy` should receive `(index, item) => ...` or a method reference.","Remove any `()` call or quotes in the template binding so the function itself is passed.","Verify the assigned value with `typeof` before setting it if it comes from dynamic code."],"exampleFix":"<!-- before -->\n<table cdk-table [dataSource]=\"data\" [trackBy]=\"'trackById'\"></table>\n\n<!-- after -->\n<table cdk-table [dataSource]=\"data\" [trackBy]=\"trackById\"></table>\n// component: trackById(index: number, row: Row) { return row.id; }","handlingStrategy":"type-guard","validationCode":"if (typeof trackById !== 'function') {\n  throw new TypeError('trackBy must be a function');\n}\ntable.trackBy = trackById;","typeGuard":"function isTrackByFn<T>(v: unknown): v is TrackByFunction<T> {\n  return typeof v === 'function';\n}","tryCatchPattern":null,"preventionTips":["Never quote or invoke trackBy in templates; pass the function reference: [trackBy]=\"trackById\".","Add a compile-time type like `trackBy: TrackByFunction<Row>` in reactive configs.","Unit-test that the bound value is a function in component tests."],"tags":["angular","cdk","table","trackby","input-validation"],"backgroundTag":"trackby-not-a-function","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}