{"record":{"id":"49752dbdf1458526","repo":"TanStack/table","slug":"corecolumnsfeature-require-an-id-when-using-a-non","errorCode":null,"errorMessage":"coreColumnsFeature require an id when using a non-string header","messagePattern":"coreColumnsFeature require an id when using a non-string header","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/table-core/src/core/columns/constructColumn.ts","lineNumber":94,"sourceCode":"          result = result?.[key]\n          if (process.env.NODE_ENV === 'development' && result === undefined) {\n            console.warn(\n              `\"${key}\" in deeply nested key \"${accessorKey}\" returned undefined.`,\n            )\n          }\n        }\n\n        return result as TValue\n      }\n    } else {\n      accessorFn = (originalRow: TData) =>\n        (originalRow as any)[resolvedColumnDef.accessorKey]\n    }\n  }\n\n  if (!id) {\n    if (process.env.NODE_ENV === 'development') {\n      throw new Error(\n        resolvedColumnDef.accessorFn\n          ? `coreColumnsFeature require an id when using an accessorFn`\n          : `coreColumnsFeature require an id when using a non-string header`,\n      )\n    }\n    throw new Error()\n  }\n\n  // Create column with shared prototype for memory efficiency\n  const columnPrototype = getColumnPrototype(table)\n  const column = Object.create(columnPrototype) as Column_CoreProperties<\n    TFeatures,\n    TData,\n    TValue\n  >\n\n  // Only assign instance-specific properties\n  column.accessorFn = accessorFn","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/TanStack/table/blob/d01c01bedbab0ff6c2641f18b2fc9a11545d9bf6/packages/table-core/src/core/columns/constructColumn.ts#L76-L112","documentation":"constructColumn throws this when a column definition has no id and its header is not a plain string, so the library cannot infer an id (only string headers or accessorKey yield an id). It is the non-accessorFn branch of the same missing-id guard, in development mode.","triggerScenarios":"Passing a columnDef with a non-string header (component/JSX/render function) and no accessorKey/accessorFn and no id, in development.","commonSituations":"Display-only columns with custom render headers (e.g. row actions, drag handles) that omit id; migrating columns from string headers to custom header components.","solutions":["Add an explicit id to the column definition.","If the column needs no accessor, still give it a stable id like 'actions'.","Keep headers as plain strings where possible so ids can be inferred."],"exampleFix":"// before\n{ header: (props) => <ActionsMenu {...props} /> }\n// after\n{ id: 'actions', header: (props) => <ActionsMenu {...props} /> }","handlingStrategy":"validation","validationCode":"function assertColumnIdOrHeader(def) {\n  const inferable = typeof def.id === 'string' || typeof def.header === 'string' || typeof def.accessorKey === 'string'\n  if (!inferable) throw new Error('Column needs an explicit id (non-string header, no accessorKey)')\n}\ncolumns.forEach(assertColumnIdOrHeader)","typeGuard":"function canInferColumnId(def: ColumnDef<any>): boolean {\n  return typeof def.id === 'string' || typeof def.header === 'string' || typeof def.accessorKey === 'string'\n}","tryCatchPattern":"try {\n  table.getColumn('actions') // built via constructColumn\n} catch (e) {\n  if ((e as Error).message.includes('require an id')) {\n    console.error('Display-only column missing id:', e)\n  } else throw e\n}","preventionTips":["Give every display-only column (actions, selection, drag) an explicit id","Add a dev-time column config validator in your app","When converting string headers to custom components, add id in the same change"],"tags":["columns","configuration","missing-id"],"backgroundTag":"column-missing-id","analyzedSha":"d01c01bedbab0ff6c2641f18b2fc9a11545d9bf6","analyzedAt":"2026-08-28T21:52:44.679Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}