TanStack/table · warning
"${key}" in deeply nested key "${accessorKey}" returned unde
Error message
"${key}" in deeply nested key "${accessorKey}" returned undefined. What it means
When resolving an accessorKey with dot notation (e.g. 'user.address.city'), constructColumn walks each key segment against the row object. If any intermediate key resolves to undefined, it logs this warning in development, indicating the accessor path does not match the actual row data shape.
Source
Thrown at packages/table-core/src/core/columns/constructColumn.ts:78
? resolvedColumnDef.header
: undefined)
let accessorFn: AccessorFn<TData, TValue> | undefined
if (resolvedColumnDef.accessorFn) {
accessorFn = resolvedColumnDef.accessorFn
} else if (accessorKey !== undefined) {
// Support deep accessor keys
if (typeof accessorKey === 'string' && accessorKey.includes('.')) {
const keys = accessorKey.split('.')
accessorFn = (originalRow: TData) => {
let result = originalRow as Record<string, any> | undefined
for (let i = 0; i < keys.length; i++) {
const key = keys[i]!
result = result?.[key]
if (process.env.NODE_ENV === 'development' && result === undefined) {
console.warn(
`"${key}" in deeply nested key "${accessorKey}" returned undefined.`,
)
}
}
return result as TValue
}
} else {
accessorFn = (originalRow: TData) =>
(originalRow as any)[resolvedColumnDef.accessorKey]
}
}
if (!id) {
if (process.env.NODE_ENV === 'development') {
throw new Error(
resolvedColumnDef.accessorFn
? `coreColumnsFeature require an id when using an accessorFn`View on GitHub (pinned to d01c01bedb)
Solutions
- Fix the accessorKey string so each dot-separated segment matches the row data exactly.
- Log one row of your data and confirm the nested path exists on every record.
- If rows legitimately lack the nested value, supply an accessorFn: row => row?.user?.address?.city ?? '' instead of accessorKey.
- Normalize/transform API data so the nested structure matches the column definition.
Example fix
// before
{ accessorKey: 'usr.profile.name', header: 'Name' }
// after
{ accessorKey: 'user.profile.name', header: 'Name' }
// or for nullable data:
{ id: 'name', accessorFn: (row) => row?.user?.profile?.name ?? '', header: 'Name' } Defensive patterns
Strategy: validation
Validate before calling
function validateAccessorKey(data: any[], accessorKey: string): boolean {
return data.every((row) =>
accessorKey.split('.').reduce<any>((o, k) => (o == null ? undefined : o[k]), row) !== undefined
)
} Type guard
function hasPath<T, P extends string>(row: T, path: P): boolean {
return path.split('.').reduce<any>((o, k) => (o == null ? undefined : o[k]), row) !== undefined
} Prevention
- Prefer accessorFn with optional chaining over dotted accessorKey for nullable nested data.
- Add a dev-time test asserting every fixture row resolves each column's accessorKey.
- Keep column accessors in sync with API response types via TypeScript types on row data.
- When the API shape changes, grep for the old path in column definitions.
When it happens
Trigger: Defining a column with accessorKey: 'a.b.c' where a row is missing property 'a' or 'b', or a typo like accessorKey: 'usr.name' when the data uses 'user.name'; rows where a nested object is null/undefined for some records.
Common situations: Backend API changes the JSON shape; inconsistent rows (some missing nested objects); typos in accessorKey; using dot notation against data that stores keys containing literal dots.
Related errors
- [Table] Column with id '${columnId}' does not exist.
- coreColumnsFeature require an id when using an accessorFn
- coreColumnsFeature require an id when using a non-string hea
- filterFn '${filterFnName}' (auto) for column '${column.id}'
- filterFn '${String(column.columnDef.filterFn)}' for column '
AI-assisted analysis of TanStack/table@d01c01bedb (2026-08-28).
Data as JSON: /api/errors/42b5718e1b3122c8.
Report an issue: GitHub.